From f01dd17b07019eec475ba482d0b5d686985146c4 Mon Sep 17 00:00:00 2001 From: Fury3K Date: Wed, 18 Mar 2026 00:26:46 +0800 Subject: [PATCH 01/22] ci: add github workflows and gemfile --- .github/workflows/deploy.yml | 164 +++++++++++++++++++++++++++++++++ .github/workflows/test.yml | 131 ++++++++++++++++++++++++++ Gemfile | 6 ++ docs/legal/privacy-policy.md | 43 +++++++++ docs/legal/terms-of-service.md | 28 ++++++ 5 files changed, 372 insertions(+) create mode 100644 .github/workflows/deploy.yml create mode 100644 .github/workflows/test.yml create mode 100644 Gemfile create mode 100644 docs/legal/privacy-policy.md create mode 100644 docs/legal/terms-of-service.md diff --git a/.github/workflows/deploy.yml b/.github/workflows/deploy.yml new file mode 100644 index 0000000..93de0db --- /dev/null +++ b/.github/workflows/deploy.yml @@ -0,0 +1,164 @@ +name: Deploy + +on: + push: + tags: + - "v*" + workflow_dispatch: + inputs: + environment: + description: "Deployment environment" + required: true + default: staging + type: choice + options: + - staging + - production + +jobs: + build-android: + name: Build Android + runs-on: ubuntu-latest + defaults: + run: + working-directory: apps/mobile + + steps: + - uses: actions/checkout@v4 + + - name: Set up Java + uses: actions/setup-java@v4 + with: + java-version: "17" + distribution: temurin + + - name: Set up Flutter + uses: subosito/flutter-action@v2 + with: + flutter-version: "3.22.x" + channel: stable + cache: true + + - name: Install dependencies + run: flutter pub get + + - name: Run code generation + run: dart run build_runner build --delete-conflicting-outputs + + - name: Decode keystore + run: | + echo "${{ secrets.ANDROID_KEYSTORE_BASE64 }}" | base64 --decode > android/app/keystore.jks + + - name: Build App Bundle + env: + KEYSTORE_PASSWORD: ${{ secrets.ANDROID_KEYSTORE_PASSWORD }} + KEY_ALIAS: ${{ secrets.ANDROID_KEY_ALIAS }} + KEY_PASSWORD: ${{ secrets.ANDROID_KEY_PASSWORD }} + run: flutter build appbundle --release + + - name: Upload AAB artifact + uses: actions/upload-artifact@v4 + with: + name: android-release + path: apps/mobile/build/app/outputs/bundle/release/app-release.aab + + build-ios: + name: Build iOS + runs-on: macos-latest + defaults: + run: + working-directory: apps/mobile + + steps: + - uses: actions/checkout@v4 + + - name: Set up Flutter + uses: subosito/flutter-action@v2 + with: + flutter-version: "3.22.x" + channel: stable + cache: true + + - name: Install Ruby + Fastlane + uses: ruby/setup-ruby@v1 + with: + ruby-version: "3.3" + bundler-cache: true + + - name: Install dependencies + run: flutter pub get + + - name: Run code generation + run: dart run build_runner build --delete-conflicting-outputs + + - name: Fastlane — certificates + working-directory: . + env: + MATCH_GIT_URL: ${{ secrets.MATCH_GIT_URL }} + MATCH_PASSWORD: ${{ secrets.MATCH_PASSWORD }} + FASTLANE_APPLE_APPLICATION_SPECIFIC_PASSWORD: ${{ secrets.FASTLANE_APP_PASSWORD }} + run: bundle exec fastlane ios certificates + + - name: Fastlane — build + working-directory: . + env: + MATCH_GIT_URL: ${{ secrets.MATCH_GIT_URL }} + MATCH_PASSWORD: ${{ secrets.MATCH_PASSWORD }} + run: bundle exec fastlane ios build + + - name: Upload IPA artifact + uses: actions/upload-artifact@v4 + with: + name: ios-release + path: apps/mobile/build/ios/iphoneos/Runner.app + + deploy-android: + name: Deploy Android + runs-on: ubuntu-latest + needs: build-android + if: github.event_name == 'push' && startsWith(github.ref, 'refs/tags/') + + steps: + - uses: actions/checkout@v4 + + - name: Download AAB + uses: actions/download-artifact@v4 + with: + name: android-release + + - name: Install Ruby + Fastlane + uses: ruby/setup-ruby@v1 + with: + ruby-version: "3.3" + bundler-cache: true + + - name: Deploy to Play Store + env: + SUPPLY_JSON_KEY: ${{ secrets.GOOGLE_PLAY_JSON_KEY }} + run: bundle exec fastlane android deploy + + deploy-ios: + name: Deploy iOS + runs-on: macos-latest + needs: build-ios + if: github.event_name == 'push' && startsWith(github.ref, 'refs/tags/') + + steps: + - uses: actions/checkout@v4 + + - name: Download IPA + uses: actions/download-artifact@v4 + with: + name: ios-release + + - name: Install Ruby + Fastlane + uses: ruby/setup-ruby@v1 + with: + ruby-version: "3.3" + bundler-cache: true + + - name: Deploy to TestFlight + env: + FASTLANE_APPLE_APPLICATION_SPECIFIC_PASSWORD: ${{ secrets.FASTLANE_APP_PASSWORD }} + FASTLANE_SESSION: ${{ secrets.FASTLANE_SESSION }} + run: bundle exec fastlane ios testflight diff --git a/.github/workflows/test.yml b/.github/workflows/test.yml new file mode 100644 index 0000000..79c6387 --- /dev/null +++ b/.github/workflows/test.yml @@ -0,0 +1,131 @@ +name: Test + +on: + pull_request: + branches: [main, develop] + push: + branches: [main, develop] + +jobs: + flutter-test: + name: Flutter Tests + runs-on: ubuntu-latest + defaults: + run: + working-directory: apps/mobile + + steps: + - uses: actions/checkout@v4 + + - name: Set up Flutter + uses: subosito/flutter-action@v2 + with: + flutter-version: "3.22.x" + channel: stable + cache: true + + - name: Install dependencies + run: flutter pub get + + - name: Run code generation + run: dart run build_runner build --delete-conflicting-outputs + + - name: Analyze + run: flutter analyze + + - name: Run unit & widget tests + run: flutter test --coverage + + - name: Upload coverage + uses: codecov/codecov-action@v4 + with: + files: apps/mobile/coverage/lcov.info + flags: flutter + + bridge-test: + name: Bridge Server Tests + runs-on: ubuntu-latest + defaults: + run: + working-directory: packages/bridge + + steps: + - uses: actions/checkout@v4 + + - name: Set up Node.js + uses: actions/setup-node@v4 + with: + node-version: "22" + cache: npm + cache-dependency-path: packages/bridge/package.json + + - name: Install dependencies + run: npm install + + - name: Type check + run: npm run typecheck + + - name: Run tests + run: npm test + + flutter-build-android: + name: Android Build Check + runs-on: ubuntu-latest + needs: flutter-test + if: github.event_name == 'push' + defaults: + run: + working-directory: apps/mobile + + steps: + - uses: actions/checkout@v4 + + - name: Set up Java + uses: actions/setup-java@v4 + with: + java-version: "17" + distribution: temurin + + - name: Set up Flutter + uses: subosito/flutter-action@v2 + with: + flutter-version: "3.22.x" + channel: stable + cache: true + + - name: Install dependencies + run: flutter pub get + + - name: Run code generation + run: dart run build_runner build --delete-conflicting-outputs + + - name: Build APK (debug) + run: flutter build apk --debug + + flutter-build-ios: + name: iOS Build Check + runs-on: macos-latest + needs: flutter-test + if: github.event_name == 'push' + defaults: + run: + working-directory: apps/mobile + + steps: + - uses: actions/checkout@v4 + + - name: Set up Flutter + uses: subosito/flutter-action@v2 + with: + flutter-version: "3.22.x" + channel: stable + cache: true + + - name: Install dependencies + run: flutter pub get + + - name: Run code generation + run: dart run build_runner build --delete-conflicting-outputs + + - name: Build iOS (no codesign) + run: flutter build ios --debug --no-codesign diff --git a/Gemfile b/Gemfile new file mode 100644 index 0000000..dc70d2e --- /dev/null +++ b/Gemfile @@ -0,0 +1,6 @@ +source "https://rubygems.org" + +gem "fastlane", "~> 2.220" + +plugins_path = File.join(File.dirname(__FILE__), "fastlane", "Pluginfile") +eval_gemfile(plugins_path) if File.exist?(plugins_path) diff --git a/docs/legal/privacy-policy.md b/docs/legal/privacy-policy.md new file mode 100644 index 0000000..42c2dec --- /dev/null +++ b/docs/legal/privacy-policy.md @@ -0,0 +1,43 @@ +# Privacy Policy + +**Last updated: 2026-03-17** + +## Overview +ReCursor ("we", "our", "the app") is an open-source mobile application for monitoring AI coding agent workflows. This policy describes what data we collect, how we use it, and your rights. + +## Data We Collect + +### Data stored locally on your device +- **Authentication tokens**: GitHub OAuth tokens or Personal Access Tokens, stored in your device's secure keychain +- **Agent configurations**: Bridge server URLs and auth tokens, stored encrypted in the app's local database +- **Session history**: Chat messages and tool call records from your AI agent sessions, stored locally in SQLite +- **App preferences**: Theme settings and notification preferences, stored in local key-value storage + +### Data we do NOT collect +- We do not operate any servers or collect any telemetry by default +- We do not transmit your code, files, or session data to any third party +- We do not use advertising identifiers +- We do not track your location + +### Optional analytics (opt-in only) +If you explicitly enable analytics in Settings, the app logs anonymized usage events locally. These events are never transmitted unless you configure a self-hosted analytics endpoint. + +## Data Transmission +ReCursor communicates only with: +1. **Your bridge server**: The app connects directly to the ReCursor bridge server running on your own machine via WebSocket. You control this server. +2. **GitHub API**: Only for authentication (OAuth token exchange or PAT validation). We do not store GitHub API responses beyond the access token. +3. **Anthropic API**: If using the Agent SDK integration, requests are made via your bridge server using your own API key. ReCursor does not have access to your Anthropic API key. + +## Security +- Authentication tokens are stored using iOS Keychain / Android Keystore via `flutter_secure_storage` +- All bridge connections use WSS (TLS-encrypted WebSocket) +- We recommend using Tailscale or WireGuard for bridge connectivity + +## Your Rights +You can delete all locally stored data by uninstalling the app or using "Sign Out" in Settings. + +## Changes +We will update this policy as the app evolves. Check the app's GitHub repository for the latest version. + +## Contact +Questions? Open an issue at https://github.com/RecursiveDev/ReCursor/issues diff --git a/docs/legal/terms-of-service.md b/docs/legal/terms-of-service.md new file mode 100644 index 0000000..bb4b276 --- /dev/null +++ b/docs/legal/terms-of-service.md @@ -0,0 +1,28 @@ +# Terms of Service + +**Last updated: 2026-03-17** + +## Acceptance +By using ReCursor, you agree to these terms. + +## What ReCursor Is +ReCursor is an open-source mobile companion app for AI coding agent workflows. It connects to a bridge server you run on your own machine. + +## Your Responsibilities +- You are responsible for the security of your bridge server +- You are responsible for your Anthropic API key usage and costs +- You must comply with Anthropic's usage policies when using the Agent SDK +- Do not use ReCursor to automate actions you are not authorized to perform + +## Disclaimer +ReCursor is provided "as is" without warranty. The developers are not responsible for: +- Code changes made by AI agents through the app +- API costs incurred through Agent SDK usage +- Data loss from local database corruption +- Security issues arising from misconfigured bridge servers + +## Open Source +ReCursor is MIT-licensed. See LICENSE for details. + +## Changes +We may update these terms. Continued use constitutes acceptance. From 22ae749118a5a5bd4dec6bfaacbb51b2e417bc91 Mon Sep 17 00:00:00 2001 From: Fury3K Date: Wed, 18 Mar 2026 00:26:52 +0800 Subject: [PATCH 02/22] feat: implement bridge server for mobile-agent communication --- packages/bridge/package-lock.json | 5470 +++++++++++++++++ packages/bridge/package.json | 31 +- .../bridge/src/agents/agent_sdk_adapter.ts | 134 + packages/bridge/src/agents/session_manager.ts | 217 + packages/bridge/src/agents/tool_executor.ts | 350 ++ packages/bridge/src/auth/rate_limiter.ts | 49 + packages/bridge/src/auth/token_validator.ts | 36 + packages/bridge/src/config.ts | 30 + packages/bridge/src/files/file_service.ts | 127 + packages/bridge/src/git/diff_parser.ts | 152 + packages/bridge/src/git/git_service.ts | 116 + packages/bridge/src/hooks/event_queue.ts | 37 + packages/bridge/src/hooks/receiver.ts | 55 + packages/bridge/src/hooks/validator.ts | 31 + packages/bridge/src/index.ts | 7 + .../bridge/src/notifications/dispatcher.ts | 59 + .../bridge/src/notifications/event_bus.ts | 33 + packages/bridge/src/server.ts | 85 + packages/bridge/src/terminal/output_stream.ts | 39 + .../bridge/src/terminal/terminal_manager.ts | 102 + packages/bridge/src/types.ts | 322 + .../src/websocket/connection_manager.ts | 83 + .../bridge/src/websocket/message_handler.ts | 298 + packages/bridge/src/websocket/server.ts | 86 + 24 files changed, 7945 insertions(+), 4 deletions(-) create mode 100644 packages/bridge/package-lock.json create mode 100644 packages/bridge/src/agents/agent_sdk_adapter.ts create mode 100644 packages/bridge/src/agents/session_manager.ts create mode 100644 packages/bridge/src/agents/tool_executor.ts create mode 100644 packages/bridge/src/auth/rate_limiter.ts create mode 100644 packages/bridge/src/auth/token_validator.ts create mode 100644 packages/bridge/src/config.ts create mode 100644 packages/bridge/src/files/file_service.ts create mode 100644 packages/bridge/src/git/diff_parser.ts create mode 100644 packages/bridge/src/git/git_service.ts create mode 100644 packages/bridge/src/hooks/event_queue.ts create mode 100644 packages/bridge/src/hooks/receiver.ts create mode 100644 packages/bridge/src/hooks/validator.ts create mode 100644 packages/bridge/src/index.ts create mode 100644 packages/bridge/src/notifications/dispatcher.ts create mode 100644 packages/bridge/src/notifications/event_bus.ts create mode 100644 packages/bridge/src/server.ts create mode 100644 packages/bridge/src/terminal/output_stream.ts create mode 100644 packages/bridge/src/terminal/terminal_manager.ts create mode 100644 packages/bridge/src/types.ts create mode 100644 packages/bridge/src/websocket/connection_manager.ts create mode 100644 packages/bridge/src/websocket/message_handler.ts create mode 100644 packages/bridge/src/websocket/server.ts diff --git a/packages/bridge/package-lock.json b/packages/bridge/package-lock.json new file mode 100644 index 0000000..747aed9 --- /dev/null +++ b/packages/bridge/package-lock.json @@ -0,0 +1,5470 @@ +{ + "name": "@recursor/bridge", + "version": "0.1.0", + "lockfileVersion": 3, + "requires": true, + "packages": { + "": { + "name": "@recursor/bridge", + "version": "0.1.0", + "license": "MIT", + "dependencies": { + "@anthropic-ai/sdk": "^0.79.0", + "cors": "^2.8.5", + "dotenv": "^16.4.7", + "express": "^4.21.1", + "simple-git": "^3.27.0", + "uuid": "^10.0.0", + "ws": "^8.18.0", + "zod": "^3.23.8" + }, + "devDependencies": { + "@types/cors": "^2.8.17", + "@types/express": "^5.0.0", + "@types/jest": "^29.5.14", + "@types/node": "^22.0.0", + "@types/uuid": "^10.0.0", + "@types/ws": "^8.5.13", + "jest": "^29.7.0", + "nodemon": "^3.1.7", + "ts-jest": "^29.2.5", + "ts-node": "^10.9.2", + "typescript": "^5.6.0" + } + }, + "node_modules/@anthropic-ai/sdk": { + "version": "0.79.0", + "resolved": "https://registry.npmjs.org/@anthropic-ai/sdk/-/sdk-0.79.0.tgz", + "integrity": "sha512-ietmtM6glcnnrWq26H+BZm8J07iay9Cob6hRzDTr/A9QWF1m2T//TQhFO4MTKcZht2/7LS8bG9wUYEhcizKRnA==", + "license": "MIT", + "dependencies": { + "json-schema-to-ts": "^3.1.1" + }, + "bin": { + "anthropic-ai-sdk": "bin/cli" + }, + "peerDependencies": { + "zod": "^3.25.0 || ^4.0.0" + }, + "peerDependenciesMeta": { + "zod": { + "optional": true + } + } + }, + "node_modules/@babel/code-frame": { + "version": "7.29.0", + "resolved": "https://registry.npmjs.org/@babel/code-frame/-/code-frame-7.29.0.tgz", + "integrity": "sha512-9NhCeYjq9+3uxgdtp20LSiJXJvN0FeCtNGpJxuMFZ1Kv3cWUNb6DOhJwUvcVCzKGR66cw4njwM6hrJLqgOwbcw==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/helper-validator-identifier": "^7.28.5", + "js-tokens": "^4.0.0", + "picocolors": "^1.1.1" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/compat-data": { + "version": "7.29.0", + "resolved": "https://registry.npmjs.org/@babel/compat-data/-/compat-data-7.29.0.tgz", + "integrity": "sha512-T1NCJqT/j9+cn8fvkt7jtwbLBfLC/1y1c7NtCeXFRgzGTsafi68MRv8yzkYSapBnFA6L3U2VSc02ciDzoAJhJg==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/core": { + "version": "7.29.0", + "resolved": "https://registry.npmjs.org/@babel/core/-/core-7.29.0.tgz", + "integrity": "sha512-CGOfOJqWjg2qW/Mb6zNsDm+u5vFQ8DxXfbM09z69p5Z6+mE1ikP2jUXw+j42Pf1XTYED2Rni5f95npYeuwMDQA==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/code-frame": "^7.29.0", + "@babel/generator": "^7.29.0", + "@babel/helper-compilation-targets": "^7.28.6", + "@babel/helper-module-transforms": "^7.28.6", + "@babel/helpers": "^7.28.6", + "@babel/parser": "^7.29.0", + "@babel/template": "^7.28.6", + "@babel/traverse": "^7.29.0", + "@babel/types": "^7.29.0", + "@jridgewell/remapping": "^2.3.5", + "convert-source-map": "^2.0.0", + "debug": "^4.1.0", + "gensync": "^1.0.0-beta.2", + "json5": "^2.2.3", + "semver": "^6.3.1" + }, + "engines": { + "node": ">=6.9.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/babel" + } + }, + "node_modules/@babel/core/node_modules/debug": { + "version": "4.4.3", + "resolved": "https://registry.npmjs.org/debug/-/debug-4.4.3.tgz", + "integrity": "sha512-RGwwWnwQvkVfavKVt22FGLw+xYSdzARwm0ru6DhTVA3umU5hZc28V3kO4stgYryrTlLpuvgI9GiijltAjNbcqA==", + "dev": true, + "license": "MIT", + "dependencies": { + "ms": "^2.1.3" + }, + "engines": { + "node": ">=6.0" + }, + "peerDependenciesMeta": { + "supports-color": { + "optional": true + } + } + }, + "node_modules/@babel/core/node_modules/ms": { + "version": "2.1.3", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.3.tgz", + "integrity": "sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==", + "dev": true, + "license": "MIT" + }, + "node_modules/@babel/generator": { + "version": "7.29.1", + "resolved": "https://registry.npmjs.org/@babel/generator/-/generator-7.29.1.tgz", + "integrity": "sha512-qsaF+9Qcm2Qv8SRIMMscAvG4O3lJ0F1GuMo5HR/Bp02LopNgnZBC/EkbevHFeGs4ls/oPz9v+Bsmzbkbe+0dUw==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/parser": "^7.29.0", + "@babel/types": "^7.29.0", + "@jridgewell/gen-mapping": "^0.3.12", + "@jridgewell/trace-mapping": "^0.3.28", + "jsesc": "^3.0.2" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/helper-compilation-targets": { + "version": "7.28.6", + "resolved": "https://registry.npmjs.org/@babel/helper-compilation-targets/-/helper-compilation-targets-7.28.6.tgz", + "integrity": "sha512-JYtls3hqi15fcx5GaSNL7SCTJ2MNmjrkHXg4FSpOA/grxK8KwyZ5bubHsCq8FXCkua6xhuaaBit+3b7+VZRfcA==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/compat-data": "^7.28.6", + "@babel/helper-validator-option": "^7.27.1", + "browserslist": "^4.24.0", + "lru-cache": "^5.1.1", + "semver": "^6.3.1" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/helper-globals": { + "version": "7.28.0", + "resolved": "https://registry.npmjs.org/@babel/helper-globals/-/helper-globals-7.28.0.tgz", + "integrity": "sha512-+W6cISkXFa1jXsDEdYA8HeevQT/FULhxzR99pxphltZcVaugps53THCeiWA8SguxxpSp3gKPiuYfSWopkLQ4hw==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/helper-module-imports": { + "version": "7.28.6", + "resolved": "https://registry.npmjs.org/@babel/helper-module-imports/-/helper-module-imports-7.28.6.tgz", + "integrity": "sha512-l5XkZK7r7wa9LucGw9LwZyyCUscb4x37JWTPz7swwFE/0FMQAGpiWUZn8u9DzkSBWEcK25jmvubfpw2dnAMdbw==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/traverse": "^7.28.6", + "@babel/types": "^7.28.6" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/helper-module-transforms": { + "version": "7.28.6", + "resolved": "https://registry.npmjs.org/@babel/helper-module-transforms/-/helper-module-transforms-7.28.6.tgz", + "integrity": "sha512-67oXFAYr2cDLDVGLXTEABjdBJZ6drElUSI7WKp70NrpyISso3plG9SAGEF6y7zbha/wOzUByWWTJvEDVNIUGcA==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/helper-module-imports": "^7.28.6", + "@babel/helper-validator-identifier": "^7.28.5", + "@babel/traverse": "^7.28.6" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0" + } + }, + "node_modules/@babel/helper-plugin-utils": { + "version": "7.28.6", + "resolved": "https://registry.npmjs.org/@babel/helper-plugin-utils/-/helper-plugin-utils-7.28.6.tgz", + "integrity": "sha512-S9gzZ/bz83GRysI7gAD4wPT/AI3uCnY+9xn+Mx/KPs2JwHJIz1W8PZkg2cqyt3RNOBM8ejcXhV6y8Og7ly/Dug==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/helper-string-parser": { + "version": "7.27.1", + "resolved": "https://registry.npmjs.org/@babel/helper-string-parser/-/helper-string-parser-7.27.1.tgz", + "integrity": "sha512-qMlSxKbpRlAridDExk92nSobyDdpPijUq2DW6oDnUqd0iOGxmQjyqhMIihI9+zv4LPyZdRje2cavWPbCbWm3eA==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/helper-validator-identifier": { + "version": "7.28.5", + "resolved": "https://registry.npmjs.org/@babel/helper-validator-identifier/-/helper-validator-identifier-7.28.5.tgz", + "integrity": "sha512-qSs4ifwzKJSV39ucNjsvc6WVHs6b7S03sOh2OcHF9UHfVPqWWALUsNUVzhSBiItjRZoLHx7nIarVjqKVusUZ1Q==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/helper-validator-option": { + "version": "7.27.1", + "resolved": "https://registry.npmjs.org/@babel/helper-validator-option/-/helper-validator-option-7.27.1.tgz", + "integrity": "sha512-YvjJow9FxbhFFKDSuFnVCe2WxXk1zWc22fFePVNEaWJEu8IrZVlda6N0uHwzZrUM1il7NC9Mlp4MaJYbYd9JSg==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/helpers": { + "version": "7.29.2", + "resolved": "https://registry.npmjs.org/@babel/helpers/-/helpers-7.29.2.tgz", + "integrity": "sha512-HoGuUs4sCZNezVEKdVcwqmZN8GoHirLUcLaYVNBK2J0DadGtdcqgr3BCbvH8+XUo4NGjNl3VOtSjEKNzqfFgKw==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/template": "^7.28.6", + "@babel/types": "^7.29.0" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/parser": { + "version": "7.29.2", + "resolved": "https://registry.npmjs.org/@babel/parser/-/parser-7.29.2.tgz", + "integrity": "sha512-4GgRzy/+fsBa72/RZVJmGKPmZu9Byn8o4MoLpmNe1m8ZfYnz5emHLQz3U4gLud6Zwl0RZIcgiLD7Uq7ySFuDLA==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/types": "^7.29.0" + }, + "bin": { + "parser": "bin/babel-parser.js" + }, + "engines": { + "node": ">=6.0.0" + } + }, + "node_modules/@babel/plugin-syntax-async-generators": { + "version": "7.8.4", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-async-generators/-/plugin-syntax-async-generators-7.8.4.tgz", + "integrity": "sha512-tycmZxkGfZaxhMRbXlPXuVFpdWlXpir2W4AMhSJgRKzk/eDlIXOhb2LHWoLpDF7TEHylV5zNhykX6KAgHJmTNw==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/helper-plugin-utils": "^7.8.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-syntax-bigint": { + "version": "7.8.3", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-bigint/-/plugin-syntax-bigint-7.8.3.tgz", + "integrity": "sha512-wnTnFlG+YxQm3vDxpGE57Pj0srRU4sHE/mDkt1qv2YJJSeUAec2ma4WLUnUPeKjyrfntVwe/N6dCXpU+zL3Npg==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/helper-plugin-utils": "^7.8.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-syntax-class-properties": { + "version": "7.12.13", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-class-properties/-/plugin-syntax-class-properties-7.12.13.tgz", + "integrity": "sha512-fm4idjKla0YahUNgFNLCB0qySdsoPiZP3iQE3rky0mBUtMZ23yDJ9SJdg6dXTSDnulOVqiF3Hgr9nbXvXTQZYA==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/helper-plugin-utils": "^7.12.13" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-syntax-class-static-block": { + "version": "7.14.5", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-class-static-block/-/plugin-syntax-class-static-block-7.14.5.tgz", + "integrity": "sha512-b+YyPmr6ldyNnM6sqYeMWE+bgJcJpO6yS4QD7ymxgH34GBPNDM/THBh8iunyvKIZztiwLH4CJZ0RxTk9emgpjw==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/helper-plugin-utils": "^7.14.5" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-syntax-import-attributes": { + "version": "7.28.6", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-import-attributes/-/plugin-syntax-import-attributes-7.28.6.tgz", + "integrity": "sha512-jiLC0ma9XkQT3TKJ9uYvlakm66Pamywo+qwL+oL8HJOvc6TWdZXVfhqJr8CCzbSGUAbDOzlGHJC1U+vRfLQDvw==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/helper-plugin-utils": "^7.28.6" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-syntax-import-meta": { + "version": "7.10.4", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-import-meta/-/plugin-syntax-import-meta-7.10.4.tgz", + "integrity": "sha512-Yqfm+XDx0+Prh3VSeEQCPU81yC+JWZ2pDPFSS4ZdpfZhp4MkFMaDC1UqseovEKwSUpnIL7+vK+Clp7bfh0iD7g==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/helper-plugin-utils": "^7.10.4" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-syntax-json-strings": { + "version": "7.8.3", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-json-strings/-/plugin-syntax-json-strings-7.8.3.tgz", + "integrity": "sha512-lY6kdGpWHvjoe2vk4WrAapEuBR69EMxZl+RoGRhrFGNYVK8mOPAW8VfbT/ZgrFbXlDNiiaxQnAtgVCZ6jv30EA==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/helper-plugin-utils": "^7.8.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-syntax-jsx": { + "version": "7.28.6", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-jsx/-/plugin-syntax-jsx-7.28.6.tgz", + "integrity": "sha512-wgEmr06G6sIpqr8YDwA2dSRTE3bJ+V0IfpzfSY3Lfgd7YWOaAdlykvJi13ZKBt8cZHfgH1IXN+CL656W3uUa4w==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/helper-plugin-utils": "^7.28.6" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-syntax-logical-assignment-operators": { + "version": "7.10.4", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-logical-assignment-operators/-/plugin-syntax-logical-assignment-operators-7.10.4.tgz", + "integrity": "sha512-d8waShlpFDinQ5MtvGU9xDAOzKH47+FFoney2baFIoMr952hKOLp1HR7VszoZvOsV/4+RRszNY7D17ba0te0ig==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/helper-plugin-utils": "^7.10.4" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-syntax-nullish-coalescing-operator": { + "version": "7.8.3", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-nullish-coalescing-operator/-/plugin-syntax-nullish-coalescing-operator-7.8.3.tgz", + "integrity": "sha512-aSff4zPII1u2QD7y+F8oDsz19ew4IGEJg9SVW+bqwpwtfFleiQDMdzA/R+UlWDzfnHFCxxleFT0PMIrR36XLNQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/helper-plugin-utils": "^7.8.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-syntax-numeric-separator": { + "version": "7.10.4", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-numeric-separator/-/plugin-syntax-numeric-separator-7.10.4.tgz", + "integrity": "sha512-9H6YdfkcK/uOnY/K7/aA2xpzaAgkQn37yzWUMRK7OaPOqOpGS1+n0H5hxT9AUw9EsSjPW8SVyMJwYRtWs3X3ug==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/helper-plugin-utils": "^7.10.4" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-syntax-object-rest-spread": { + "version": "7.8.3", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-object-rest-spread/-/plugin-syntax-object-rest-spread-7.8.3.tgz", + "integrity": "sha512-XoqMijGZb9y3y2XskN+P1wUGiVwWZ5JmoDRwx5+3GmEplNyVM2s2Dg8ILFQm8rWM48orGy5YpI5Bl8U1y7ydlA==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/helper-plugin-utils": "^7.8.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-syntax-optional-catch-binding": { + "version": "7.8.3", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-optional-catch-binding/-/plugin-syntax-optional-catch-binding-7.8.3.tgz", + "integrity": "sha512-6VPD0Pc1lpTqw0aKoeRTMiB+kWhAoT24PA+ksWSBrFtl5SIRVpZlwN3NNPQjehA2E/91FV3RjLWoVTglWcSV3Q==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/helper-plugin-utils": "^7.8.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-syntax-optional-chaining": { + "version": "7.8.3", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-optional-chaining/-/plugin-syntax-optional-chaining-7.8.3.tgz", + "integrity": "sha512-KoK9ErH1MBlCPxV0VANkXW2/dw4vlbGDrFgz8bmUsBGYkFRcbRwMh6cIJubdPrkxRwuGdtCk0v/wPTKbQgBjkg==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/helper-plugin-utils": "^7.8.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-syntax-private-property-in-object": { + "version": "7.14.5", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-private-property-in-object/-/plugin-syntax-private-property-in-object-7.14.5.tgz", + "integrity": "sha512-0wVnp9dxJ72ZUJDV27ZfbSj6iHLoytYZmh3rFcxNnvsJF3ktkzLDZPy/mA17HGsaQT3/DQsWYX1f1QGWkCoVUg==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/helper-plugin-utils": "^7.14.5" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-syntax-top-level-await": { + "version": "7.14.5", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-top-level-await/-/plugin-syntax-top-level-await-7.14.5.tgz", + "integrity": "sha512-hx++upLv5U1rgYfwe1xBQUhRmU41NEvpUvrp8jkrSCdvGSnM5/qdRMtylJ6PG5OFkBaHkbTAKTnd3/YyESRHFw==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/helper-plugin-utils": "^7.14.5" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-syntax-typescript": { + "version": "7.28.6", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-typescript/-/plugin-syntax-typescript-7.28.6.tgz", + "integrity": "sha512-+nDNmQye7nlnuuHDboPbGm00Vqg3oO8niRRL27/4LYHUsHYh0zJ1xWOz0uRwNFmM1Avzk8wZbc6rdiYhomzv/A==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/helper-plugin-utils": "^7.28.6" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/runtime": { + "version": "7.29.2", + "resolved": "https://registry.npmjs.org/@babel/runtime/-/runtime-7.29.2.tgz", + "integrity": "sha512-JiDShH45zKHWyGe4ZNVRrCjBz8Nh9TMmZG1kh4QTK8hCBTWBi8Da+i7s1fJw7/lYpM4ccepSNfqzZ/QvABBi5g==", + "license": "MIT", + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/template": { + "version": "7.28.6", + "resolved": "https://registry.npmjs.org/@babel/template/-/template-7.28.6.tgz", + "integrity": "sha512-YA6Ma2KsCdGb+WC6UpBVFJGXL58MDA6oyONbjyF/+5sBgxY/dwkhLogbMT2GXXyU84/IhRw/2D1Os1B/giz+BQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/code-frame": "^7.28.6", + "@babel/parser": "^7.28.6", + "@babel/types": "^7.28.6" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/traverse": { + "version": "7.29.0", + "resolved": "https://registry.npmjs.org/@babel/traverse/-/traverse-7.29.0.tgz", + "integrity": "sha512-4HPiQr0X7+waHfyXPZpWPfWL/J7dcN1mx9gL6WdQVMbPnF3+ZhSMs8tCxN7oHddJE9fhNE7+lxdnlyemKfJRuA==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/code-frame": "^7.29.0", + "@babel/generator": "^7.29.0", + "@babel/helper-globals": "^7.28.0", + "@babel/parser": "^7.29.0", + "@babel/template": "^7.28.6", + "@babel/types": "^7.29.0", + "debug": "^4.3.1" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/traverse/node_modules/debug": { + "version": "4.4.3", + "resolved": "https://registry.npmjs.org/debug/-/debug-4.4.3.tgz", + "integrity": "sha512-RGwwWnwQvkVfavKVt22FGLw+xYSdzARwm0ru6DhTVA3umU5hZc28V3kO4stgYryrTlLpuvgI9GiijltAjNbcqA==", + "dev": true, + "license": "MIT", + "dependencies": { + "ms": "^2.1.3" + }, + "engines": { + "node": ">=6.0" + }, + "peerDependenciesMeta": { + "supports-color": { + "optional": true + } + } + }, + "node_modules/@babel/traverse/node_modules/ms": { + "version": "2.1.3", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.3.tgz", + "integrity": "sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==", + "dev": true, + "license": "MIT" + }, + "node_modules/@babel/types": { + "version": "7.29.0", + "resolved": "https://registry.npmjs.org/@babel/types/-/types-7.29.0.tgz", + "integrity": "sha512-LwdZHpScM4Qz8Xw2iKSzS+cfglZzJGvofQICy7W7v4caru4EaAmyUuO6BGrbyQ2mYV11W0U8j5mBhd14dd3B0A==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/helper-string-parser": "^7.27.1", + "@babel/helper-validator-identifier": "^7.28.5" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@bcoe/v8-coverage": { + "version": "0.2.3", + "resolved": "https://registry.npmjs.org/@bcoe/v8-coverage/-/v8-coverage-0.2.3.tgz", + "integrity": "sha512-0hYQ8SB4Db5zvZB4axdMHGwEaQjkZzFjQiN9LVYvIFB2nSUHW9tYpxWriPrWDASIxiaXax83REcLxuSdnGPZtw==", + "dev": true, + "license": "MIT" + }, + "node_modules/@cspotcode/source-map-support": { + "version": "0.8.1", + "resolved": "https://registry.npmjs.org/@cspotcode/source-map-support/-/source-map-support-0.8.1.tgz", + "integrity": "sha512-IchNf6dN4tHoMFIn/7OE8LWZ19Y6q/67Bmf6vnGREv8RSbBVb9LPJxEcnwrcwX6ixSvaiGoomAUvu4YSxXrVgw==", + "dev": true, + "license": "MIT", + "dependencies": { + "@jridgewell/trace-mapping": "0.3.9" + }, + "engines": { + "node": ">=12" + } + }, + "node_modules/@cspotcode/source-map-support/node_modules/@jridgewell/trace-mapping": { + "version": "0.3.9", + "resolved": "https://registry.npmjs.org/@jridgewell/trace-mapping/-/trace-mapping-0.3.9.tgz", + "integrity": "sha512-3Belt6tdc8bPgAtbcmdtNJlirVoTmEb5e2gC94PnkwEW9jI6CAHUeoG85tjWP5WquqfavoMtMwiG4P926ZKKuQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "@jridgewell/resolve-uri": "^3.0.3", + "@jridgewell/sourcemap-codec": "^1.4.10" + } + }, + "node_modules/@istanbuljs/load-nyc-config": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/@istanbuljs/load-nyc-config/-/load-nyc-config-1.1.0.tgz", + "integrity": "sha512-VjeHSlIzpv/NyD3N0YuHfXOPDIixcA1q2ZV98wsMqcYlPmv2n3Yb2lYP9XMElnaFVXg5A7YLTeLu6V84uQDjmQ==", + "dev": true, + "license": "ISC", + "dependencies": { + "camelcase": "^5.3.1", + "find-up": "^4.1.0", + "get-package-type": "^0.1.0", + "js-yaml": "^3.13.1", + "resolve-from": "^5.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/@istanbuljs/schema": { + "version": "0.1.3", + "resolved": "https://registry.npmjs.org/@istanbuljs/schema/-/schema-0.1.3.tgz", + "integrity": "sha512-ZXRY4jNvVgSVQ8DL3LTcakaAtXwTVUxE81hslsyD2AtoXW/wVob10HkOJ1X/pAlcI7D+2YoZKg5do8G/w6RYgA==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=8" + } + }, + "node_modules/@jest/console": { + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/@jest/console/-/console-29.7.0.tgz", + "integrity": "sha512-5Ni4CU7XHQi32IJ398EEP4RrB8eV09sXP2ROqD4bksHrnTree52PsxvX8tpL8LvTZ3pFzXyPbNQReSN41CAhOg==", + "dev": true, + "license": "MIT", + "dependencies": { + "@jest/types": "^29.6.3", + "@types/node": "*", + "chalk": "^4.0.0", + "jest-message-util": "^29.7.0", + "jest-util": "^29.7.0", + "slash": "^3.0.0" + }, + "engines": { + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + } + }, + "node_modules/@jest/core": { + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/@jest/core/-/core-29.7.0.tgz", + "integrity": "sha512-n7aeXWKMnGtDA48y8TLWJPJmLmmZ642Ceo78cYWEpiD7FzDgmNDV/GCVRorPABdXLJZ/9wzzgZAlHjXjxDHGsg==", + "dev": true, + "license": "MIT", + "dependencies": { + "@jest/console": "^29.7.0", + "@jest/reporters": "^29.7.0", + "@jest/test-result": "^29.7.0", + "@jest/transform": "^29.7.0", + "@jest/types": "^29.6.3", + "@types/node": "*", + "ansi-escapes": "^4.2.1", + "chalk": "^4.0.0", + "ci-info": "^3.2.0", + "exit": "^0.1.2", + "graceful-fs": "^4.2.9", + "jest-changed-files": "^29.7.0", + "jest-config": "^29.7.0", + "jest-haste-map": "^29.7.0", + "jest-message-util": "^29.7.0", + "jest-regex-util": "^29.6.3", + "jest-resolve": "^29.7.0", + "jest-resolve-dependencies": "^29.7.0", + "jest-runner": "^29.7.0", + "jest-runtime": "^29.7.0", + "jest-snapshot": "^29.7.0", + "jest-util": "^29.7.0", + "jest-validate": "^29.7.0", + "jest-watcher": "^29.7.0", + "micromatch": "^4.0.4", + "pretty-format": "^29.7.0", + "slash": "^3.0.0", + "strip-ansi": "^6.0.0" + }, + "engines": { + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + }, + "peerDependencies": { + "node-notifier": "^8.0.1 || ^9.0.0 || ^10.0.0" + }, + "peerDependenciesMeta": { + "node-notifier": { + "optional": true + } + } + }, + "node_modules/@jest/environment": { + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/@jest/environment/-/environment-29.7.0.tgz", + "integrity": "sha512-aQIfHDq33ExsN4jP1NWGXhxgQ/wixs60gDiKO+XVMd8Mn0NWPWgc34ZQDTb2jKaUWQ7MuwoitXAsN2XVXNMpAw==", + "dev": true, + "license": "MIT", + "dependencies": { + "@jest/fake-timers": "^29.7.0", + "@jest/types": "^29.6.3", + "@types/node": "*", + "jest-mock": "^29.7.0" + }, + "engines": { + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + } + }, + "node_modules/@jest/expect": { + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/@jest/expect/-/expect-29.7.0.tgz", + "integrity": "sha512-8uMeAMycttpva3P1lBHB8VciS9V0XAr3GymPpipdyQXbBcuhkLQOSe8E/p92RyAdToS6ZD1tFkX+CkhoECE0dQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "expect": "^29.7.0", + "jest-snapshot": "^29.7.0" + }, + "engines": { + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + } + }, + "node_modules/@jest/expect-utils": { + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/@jest/expect-utils/-/expect-utils-29.7.0.tgz", + "integrity": "sha512-GlsNBWiFQFCVi9QVSx7f5AgMeLxe9YCCs5PuP2O2LdjDAA8Jh9eX7lA1Jq/xdXw3Wb3hyvlFNfZIfcRetSzYcA==", + "dev": true, + "license": "MIT", + "dependencies": { + "jest-get-type": "^29.6.3" + }, + "engines": { + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + } + }, + "node_modules/@jest/fake-timers": { + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/@jest/fake-timers/-/fake-timers-29.7.0.tgz", + "integrity": "sha512-q4DH1Ha4TTFPdxLsqDXK1d3+ioSL7yL5oCMJZgDYm6i+6CygW5E5xVr/D1HdsGxjt1ZWSfUAs9OxSB/BNelWrQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "@jest/types": "^29.6.3", + "@sinonjs/fake-timers": "^10.0.2", + "@types/node": "*", + "jest-message-util": "^29.7.0", + "jest-mock": "^29.7.0", + "jest-util": "^29.7.0" + }, + "engines": { + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + } + }, + "node_modules/@jest/globals": { + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/@jest/globals/-/globals-29.7.0.tgz", + "integrity": "sha512-mpiz3dutLbkW2MNFubUGUEVLkTGiqW6yLVTA+JbP6fI6J5iL9Y0Nlg8k95pcF8ctKwCS7WVxteBs29hhfAotzQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "@jest/environment": "^29.7.0", + "@jest/expect": "^29.7.0", + "@jest/types": "^29.6.3", + "jest-mock": "^29.7.0" + }, + "engines": { + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + } + }, + "node_modules/@jest/reporters": { + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/@jest/reporters/-/reporters-29.7.0.tgz", + "integrity": "sha512-DApq0KJbJOEzAFYjHADNNxAE3KbhxQB1y5Kplb5Waqw6zVbuWatSnMjE5gs8FUgEPmNsnZA3NCWl9NG0ia04Pg==", + "dev": true, + "license": "MIT", + "dependencies": { + "@bcoe/v8-coverage": "^0.2.3", + "@jest/console": "^29.7.0", + "@jest/test-result": "^29.7.0", + "@jest/transform": "^29.7.0", + "@jest/types": "^29.6.3", + "@jridgewell/trace-mapping": "^0.3.18", + "@types/node": "*", + "chalk": "^4.0.0", + "collect-v8-coverage": "^1.0.0", + "exit": "^0.1.2", + "glob": "^7.1.3", + "graceful-fs": "^4.2.9", + "istanbul-lib-coverage": "^3.0.0", + "istanbul-lib-instrument": "^6.0.0", + "istanbul-lib-report": "^3.0.0", + "istanbul-lib-source-maps": "^4.0.0", + "istanbul-reports": "^3.1.3", + "jest-message-util": "^29.7.0", + "jest-util": "^29.7.0", + "jest-worker": "^29.7.0", + "slash": "^3.0.0", + "string-length": "^4.0.1", + "strip-ansi": "^6.0.0", + "v8-to-istanbul": "^9.0.1" + }, + "engines": { + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + }, + "peerDependencies": { + "node-notifier": "^8.0.1 || ^9.0.0 || ^10.0.0" + }, + "peerDependenciesMeta": { + "node-notifier": { + "optional": true + } + } + }, + "node_modules/@jest/schemas": { + "version": "29.6.3", + "resolved": "https://registry.npmjs.org/@jest/schemas/-/schemas-29.6.3.tgz", + "integrity": "sha512-mo5j5X+jIZmJQveBKeS/clAueipV7KgiX1vMgCxam1RNYiqE1w62n0/tJJnHtjW8ZHcQco5gY85jA3mi0L+nSA==", + "dev": true, + "license": "MIT", + "dependencies": { + "@sinclair/typebox": "^0.27.8" + }, + "engines": { + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + } + }, + "node_modules/@jest/source-map": { + "version": "29.6.3", + "resolved": "https://registry.npmjs.org/@jest/source-map/-/source-map-29.6.3.tgz", + "integrity": "sha512-MHjT95QuipcPrpLM+8JMSzFx6eHp5Bm+4XeFDJlwsvVBjmKNiIAvasGK2fxz2WbGRlnvqehFbh07MMa7n3YJnw==", + "dev": true, + "license": "MIT", + "dependencies": { + "@jridgewell/trace-mapping": "^0.3.18", + "callsites": "^3.0.0", + "graceful-fs": "^4.2.9" + }, + "engines": { + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + } + }, + "node_modules/@jest/test-result": { + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/@jest/test-result/-/test-result-29.7.0.tgz", + "integrity": "sha512-Fdx+tv6x1zlkJPcWXmMDAG2HBnaR9XPSd5aDWQVsfrZmLVT3lU1cwyxLgRmXR9yrq4NBoEm9BMsfgFzTQAbJYA==", + "dev": true, + "license": "MIT", + "dependencies": { + "@jest/console": "^29.7.0", + "@jest/types": "^29.6.3", + "@types/istanbul-lib-coverage": "^2.0.0", + "collect-v8-coverage": "^1.0.0" + }, + "engines": { + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + } + }, + "node_modules/@jest/test-sequencer": { + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/@jest/test-sequencer/-/test-sequencer-29.7.0.tgz", + "integrity": "sha512-GQwJ5WZVrKnOJuiYiAF52UNUJXgTZx1NHjFSEB0qEMmSZKAkdMoIzw/Cj6x6NF4AvV23AUqDpFzQkN/eYCYTxw==", + "dev": true, + "license": "MIT", + "dependencies": { + "@jest/test-result": "^29.7.0", + "graceful-fs": "^4.2.9", + "jest-haste-map": "^29.7.0", + "slash": "^3.0.0" + }, + "engines": { + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + } + }, + "node_modules/@jest/transform": { + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/@jest/transform/-/transform-29.7.0.tgz", + "integrity": "sha512-ok/BTPFzFKVMwO5eOHRrvnBVHdRy9IrsrW1GpMaQ9MCnilNLXQKmAX8s1YXDFaai9xJpac2ySzV0YeRRECr2Vw==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/core": "^7.11.6", + "@jest/types": "^29.6.3", + "@jridgewell/trace-mapping": "^0.3.18", + "babel-plugin-istanbul": "^6.1.1", + "chalk": "^4.0.0", + "convert-source-map": "^2.0.0", + "fast-json-stable-stringify": "^2.1.0", + "graceful-fs": "^4.2.9", + "jest-haste-map": "^29.7.0", + "jest-regex-util": "^29.6.3", + "jest-util": "^29.7.0", + "micromatch": "^4.0.4", + "pirates": "^4.0.4", + "slash": "^3.0.0", + "write-file-atomic": "^4.0.2" + }, + "engines": { + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + } + }, + "node_modules/@jest/types": { + "version": "29.6.3", + "resolved": "https://registry.npmjs.org/@jest/types/-/types-29.6.3.tgz", + "integrity": "sha512-u3UPsIilWKOM3F9CXtrG8LEJmNxwoCQC/XVj4IKYXvvpx7QIi/Kg1LI5uDmDpKlac62NUtX7eLjRh+jVZcLOzw==", + "dev": true, + "license": "MIT", + "dependencies": { + "@jest/schemas": "^29.6.3", + "@types/istanbul-lib-coverage": "^2.0.0", + "@types/istanbul-reports": "^3.0.0", + "@types/node": "*", + "@types/yargs": "^17.0.8", + "chalk": "^4.0.0" + }, + "engines": { + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + } + }, + "node_modules/@jridgewell/gen-mapping": { + "version": "0.3.13", + "resolved": "https://registry.npmjs.org/@jridgewell/gen-mapping/-/gen-mapping-0.3.13.tgz", + "integrity": "sha512-2kkt/7niJ6MgEPxF0bYdQ6etZaA+fQvDcLKckhy1yIQOzaoKjBBjSj63/aLVjYE3qhRt5dvM+uUyfCg6UKCBbA==", + "dev": true, + "license": "MIT", + "dependencies": { + "@jridgewell/sourcemap-codec": "^1.5.0", + "@jridgewell/trace-mapping": "^0.3.24" + } + }, + "node_modules/@jridgewell/remapping": { + "version": "2.3.5", + "resolved": "https://registry.npmjs.org/@jridgewell/remapping/-/remapping-2.3.5.tgz", + "integrity": "sha512-LI9u/+laYG4Ds1TDKSJW2YPrIlcVYOwi2fUC6xB43lueCjgxV4lffOCZCtYFiH6TNOX+tQKXx97T4IKHbhyHEQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "@jridgewell/gen-mapping": "^0.3.5", + "@jridgewell/trace-mapping": "^0.3.24" + } + }, + "node_modules/@jridgewell/resolve-uri": { + "version": "3.1.2", + "resolved": "https://registry.npmjs.org/@jridgewell/resolve-uri/-/resolve-uri-3.1.2.tgz", + "integrity": "sha512-bRISgCIjP20/tbWSPWMEi54QVPRZExkuD9lJL+UIxUKtwVJA8wW1Trb1jMs1RFXo1CBTNZ/5hpC9QvmKWdopKw==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=6.0.0" + } + }, + "node_modules/@jridgewell/sourcemap-codec": { + "version": "1.5.5", + "resolved": "https://registry.npmjs.org/@jridgewell/sourcemap-codec/-/sourcemap-codec-1.5.5.tgz", + "integrity": "sha512-cYQ9310grqxueWbl+WuIUIaiUaDcj7WOq5fVhEljNVgRfOUhY9fy2zTvfoqWsnebh8Sl70VScFbICvJnLKB0Og==", + "dev": true, + "license": "MIT" + }, + "node_modules/@jridgewell/trace-mapping": { + "version": "0.3.31", + "resolved": "https://registry.npmjs.org/@jridgewell/trace-mapping/-/trace-mapping-0.3.31.tgz", + "integrity": "sha512-zzNR+SdQSDJzc8joaeP8QQoCQr8NuYx2dIIytl1QeBEZHJ9uW6hebsrYgbz8hJwUQao3TWCMtmfV8Nu1twOLAw==", + "dev": true, + "license": "MIT", + "dependencies": { + "@jridgewell/resolve-uri": "^3.1.0", + "@jridgewell/sourcemap-codec": "^1.4.14" + } + }, + "node_modules/@kwsites/file-exists": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/@kwsites/file-exists/-/file-exists-1.1.1.tgz", + "integrity": "sha512-m9/5YGR18lIwxSFDwfE3oA7bWuq9kdau6ugN4H2rJeyhFQZcG9AgSHkQtSD15a8WvTgfz9aikZMrKPHvbpqFiw==", + "license": "MIT", + "dependencies": { + "debug": "^4.1.1" + } + }, + "node_modules/@kwsites/file-exists/node_modules/debug": { + "version": "4.4.3", + "resolved": "https://registry.npmjs.org/debug/-/debug-4.4.3.tgz", + "integrity": "sha512-RGwwWnwQvkVfavKVt22FGLw+xYSdzARwm0ru6DhTVA3umU5hZc28V3kO4stgYryrTlLpuvgI9GiijltAjNbcqA==", + "license": "MIT", + "dependencies": { + "ms": "^2.1.3" + }, + "engines": { + "node": ">=6.0" + }, + "peerDependenciesMeta": { + "supports-color": { + "optional": true + } + } + }, + "node_modules/@kwsites/file-exists/node_modules/ms": { + "version": "2.1.3", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.3.tgz", + "integrity": "sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==", + "license": "MIT" + }, + "node_modules/@kwsites/promise-deferred": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/@kwsites/promise-deferred/-/promise-deferred-1.1.1.tgz", + "integrity": "sha512-GaHYm+c0O9MjZRu0ongGBRbinu8gVAMd2UZjji6jVmqKtZluZnptXGWhz1E8j8D2HJ3f/yMxKAUC0b+57wncIw==", + "license": "MIT" + }, + "node_modules/@sinclair/typebox": { + "version": "0.27.10", + "resolved": "https://registry.npmjs.org/@sinclair/typebox/-/typebox-0.27.10.tgz", + "integrity": "sha512-MTBk/3jGLNB2tVxv6uLlFh1iu64iYOQ2PbdOSK3NW8JZsmlaOh2q6sdtKowBhfw8QFLmYNzTW4/oK4uATIi6ZA==", + "dev": true, + "license": "MIT" + }, + "node_modules/@sinonjs/commons": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/@sinonjs/commons/-/commons-3.0.1.tgz", + "integrity": "sha512-K3mCHKQ9sVh8o1C9cxkwxaOmXoAMlDxC1mYyHrjqOWEcBjYr76t96zL2zlj5dUGZ3HSw240X1qgH3Mjf1yJWpQ==", + "dev": true, + "license": "BSD-3-Clause", + "dependencies": { + "type-detect": "4.0.8" + } + }, + "node_modules/@sinonjs/fake-timers": { + "version": "10.3.0", + "resolved": "https://registry.npmjs.org/@sinonjs/fake-timers/-/fake-timers-10.3.0.tgz", + "integrity": "sha512-V4BG07kuYSUkTCSBHG8G8TNhM+F19jXFWnQtzj+we8DrkpSBCee9Z3Ms8yiGer/dlmhe35/Xdgyo3/0rQKg7YA==", + "dev": true, + "license": "BSD-3-Clause", + "dependencies": { + "@sinonjs/commons": "^3.0.0" + } + }, + "node_modules/@tsconfig/node10": { + "version": "1.0.12", + "resolved": "https://registry.npmjs.org/@tsconfig/node10/-/node10-1.0.12.tgz", + "integrity": "sha512-UCYBaeFvM11aU2y3YPZ//O5Rhj+xKyzy7mvcIoAjASbigy8mHMryP5cK7dgjlz2hWxh1g5pLw084E0a/wlUSFQ==", + "dev": true, + "license": "MIT" + }, + "node_modules/@tsconfig/node12": { + "version": "1.0.11", + "resolved": "https://registry.npmjs.org/@tsconfig/node12/-/node12-1.0.11.tgz", + "integrity": "sha512-cqefuRsh12pWyGsIoBKJA9luFu3mRxCA+ORZvA4ktLSzIuCUtWVxGIuXigEwO5/ywWFMZ2QEGKWvkZG1zDMTag==", + "dev": true, + "license": "MIT" + }, + "node_modules/@tsconfig/node14": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/@tsconfig/node14/-/node14-1.0.3.tgz", + "integrity": "sha512-ysT8mhdixWK6Hw3i1V2AeRqZ5WfXg1G43mqoYlM2nc6388Fq5jcXyr5mRsqViLx/GJYdoL0bfXD8nmF+Zn/Iow==", + "dev": true, + "license": "MIT" + }, + "node_modules/@tsconfig/node16": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/@tsconfig/node16/-/node16-1.0.4.tgz", + "integrity": "sha512-vxhUy4J8lyeyinH7Azl1pdd43GJhZH/tP2weN8TntQblOY+A0XbT8DJk1/oCPuOOyg/Ja757rG0CgHcWC8OfMA==", + "dev": true, + "license": "MIT" + }, + "node_modules/@types/babel__core": { + "version": "7.20.5", + "resolved": "https://registry.npmjs.org/@types/babel__core/-/babel__core-7.20.5.tgz", + "integrity": "sha512-qoQprZvz5wQFJwMDqeseRXWv3rqMvhgpbXFfVyWhbx9X47POIA6i/+dXefEmZKoAgOaTdaIgNSMqMIU61yRyzA==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/parser": "^7.20.7", + "@babel/types": "^7.20.7", + "@types/babel__generator": "*", + "@types/babel__template": "*", + "@types/babel__traverse": "*" + } + }, + "node_modules/@types/babel__generator": { + "version": "7.27.0", + "resolved": "https://registry.npmjs.org/@types/babel__generator/-/babel__generator-7.27.0.tgz", + "integrity": "sha512-ufFd2Xi92OAVPYsy+P4n7/U7e68fex0+Ee8gSG9KX7eo084CWiQ4sdxktvdl0bOPupXtVJPY19zk6EwWqUQ8lg==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/types": "^7.0.0" + } + }, + "node_modules/@types/babel__template": { + "version": "7.4.4", + "resolved": "https://registry.npmjs.org/@types/babel__template/-/babel__template-7.4.4.tgz", + "integrity": "sha512-h/NUaSyG5EyxBIp8YRxo4RMe2/qQgvyowRwVMzhYhBCONbW8PUsg4lkFMrhgZhUe5z3L3MiLDuvyJ/CaPa2A8A==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/parser": "^7.1.0", + "@babel/types": "^7.0.0" + } + }, + "node_modules/@types/babel__traverse": { + "version": "7.28.0", + "resolved": "https://registry.npmjs.org/@types/babel__traverse/-/babel__traverse-7.28.0.tgz", + "integrity": "sha512-8PvcXf70gTDZBgt9ptxJ8elBeBjcLOAcOtoO/mPJjtji1+CdGbHgm77om1GrsPxsiE+uXIpNSK64UYaIwQXd4Q==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/types": "^7.28.2" + } + }, + "node_modules/@types/body-parser": { + "version": "1.19.6", + "resolved": "https://registry.npmjs.org/@types/body-parser/-/body-parser-1.19.6.tgz", + "integrity": "sha512-HLFeCYgz89uk22N5Qg3dvGvsv46B8GLvKKo1zKG4NybA8U2DiEO3w9lqGg29t/tfLRJpJ6iQxnVw4OnB7MoM9g==", + "dev": true, + "license": "MIT", + "dependencies": { + "@types/connect": "*", + "@types/node": "*" + } + }, + "node_modules/@types/connect": { + "version": "3.4.38", + "resolved": "https://registry.npmjs.org/@types/connect/-/connect-3.4.38.tgz", + "integrity": "sha512-K6uROf1LD88uDQqJCktA4yzL1YYAK6NgfsI0v/mTgyPKWsX1CnJ0XPSDhViejru1GcRkLWb8RlzFYJRqGUbaug==", + "dev": true, + "license": "MIT", + "dependencies": { + "@types/node": "*" + } + }, + "node_modules/@types/cors": { + "version": "2.8.19", + "resolved": "https://registry.npmjs.org/@types/cors/-/cors-2.8.19.tgz", + "integrity": "sha512-mFNylyeyqN93lfe/9CSxOGREz8cpzAhH+E93xJ4xWQf62V8sQ/24reV2nyzUWM6H6Xji+GGHpkbLe7pVoUEskg==", + "dev": true, + "license": "MIT", + "dependencies": { + "@types/node": "*" + } + }, + "node_modules/@types/express": { + "version": "5.0.6", + "resolved": "https://registry.npmjs.org/@types/express/-/express-5.0.6.tgz", + "integrity": "sha512-sKYVuV7Sv9fbPIt/442koC7+IIwK5olP1KWeD88e/idgoJqDm3JV/YUiPwkoKK92ylff2MGxSz1CSjsXelx0YA==", + "dev": true, + "license": "MIT", + "dependencies": { + "@types/body-parser": "*", + "@types/express-serve-static-core": "^5.0.0", + "@types/serve-static": "^2" + } + }, + "node_modules/@types/express-serve-static-core": { + "version": "5.1.1", + "resolved": "https://registry.npmjs.org/@types/express-serve-static-core/-/express-serve-static-core-5.1.1.tgz", + "integrity": "sha512-v4zIMr/cX7/d2BpAEX3KNKL/JrT1s43s96lLvvdTmza1oEvDudCqK9aF/djc/SWgy8Yh0h30TZx5VpzqFCxk5A==", + "dev": true, + "license": "MIT", + "dependencies": { + "@types/node": "*", + "@types/qs": "*", + "@types/range-parser": "*", + "@types/send": "*" + } + }, + "node_modules/@types/graceful-fs": { + "version": "4.1.9", + "resolved": "https://registry.npmjs.org/@types/graceful-fs/-/graceful-fs-4.1.9.tgz", + "integrity": "sha512-olP3sd1qOEe5dXTSaFvQG+02VdRXcdytWLAZsAq1PecU8uqQAhkrnbli7DagjtXKW/Bl7YJbUsa8MPcuc8LHEQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "@types/node": "*" + } + }, + "node_modules/@types/http-errors": { + "version": "2.0.5", + "resolved": "https://registry.npmjs.org/@types/http-errors/-/http-errors-2.0.5.tgz", + "integrity": "sha512-r8Tayk8HJnX0FztbZN7oVqGccWgw98T/0neJphO91KkmOzug1KkofZURD4UaD5uH8AqcFLfdPErnBod0u71/qg==", + "dev": true, + "license": "MIT" + }, + "node_modules/@types/istanbul-lib-coverage": { + "version": "2.0.6", + "resolved": "https://registry.npmjs.org/@types/istanbul-lib-coverage/-/istanbul-lib-coverage-2.0.6.tgz", + "integrity": "sha512-2QF/t/auWm0lsy8XtKVPG19v3sSOQlJe/YHZgfjb/KBBHOGSV+J2q/S671rcq9uTBrLAXmZpqJiaQbMT+zNU1w==", + "dev": true, + "license": "MIT" + }, + "node_modules/@types/istanbul-lib-report": { + "version": "3.0.3", + "resolved": "https://registry.npmjs.org/@types/istanbul-lib-report/-/istanbul-lib-report-3.0.3.tgz", + "integrity": "sha512-NQn7AHQnk/RSLOxrBbGyJM/aVQ+pjj5HCgasFxc0K/KhoATfQ/47AyUl15I2yBUpihjmas+a+VJBOqecrFH+uA==", + "dev": true, + "license": "MIT", + "dependencies": { + "@types/istanbul-lib-coverage": "*" + } + }, + "node_modules/@types/istanbul-reports": { + "version": "3.0.4", + "resolved": "https://registry.npmjs.org/@types/istanbul-reports/-/istanbul-reports-3.0.4.tgz", + "integrity": "sha512-pk2B1NWalF9toCRu6gjBzR69syFjP4Od8WRAX+0mmf9lAjCRicLOWc+ZrxZHx/0XRjotgkF9t6iaMJ+aXcOdZQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "@types/istanbul-lib-report": "*" + } + }, + "node_modules/@types/jest": { + "version": "29.5.14", + "resolved": "https://registry.npmjs.org/@types/jest/-/jest-29.5.14.tgz", + "integrity": "sha512-ZN+4sdnLUbo8EVvVc2ao0GFW6oVrQRPn4K2lglySj7APvSrgzxHiNNK99us4WDMi57xxA2yggblIAMNhXOotLQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "expect": "^29.0.0", + "pretty-format": "^29.0.0" + } + }, + "node_modules/@types/node": { + "version": "22.19.15", + "resolved": "https://registry.npmjs.org/@types/node/-/node-22.19.15.tgz", + "integrity": "sha512-F0R/h2+dsy5wJAUe3tAU6oqa2qbWY5TpNfL/RGmo1y38hiyO1w3x2jPtt76wmuaJI4DQnOBu21cNXQ2STIUUWg==", + "dev": true, + "license": "MIT", + "peer": true, + "dependencies": { + "undici-types": "~6.21.0" + } + }, + "node_modules/@types/qs": { + "version": "6.15.0", + "resolved": "https://registry.npmjs.org/@types/qs/-/qs-6.15.0.tgz", + "integrity": "sha512-JawvT8iBVWpzTrz3EGw9BTQFg3BQNmwERdKE22vlTxawwtbyUSlMppvZYKLZzB5zgACXdXxbD3m1bXaMqP/9ow==", + "dev": true, + "license": "MIT" + }, + "node_modules/@types/range-parser": { + "version": "1.2.7", + "resolved": "https://registry.npmjs.org/@types/range-parser/-/range-parser-1.2.7.tgz", + "integrity": "sha512-hKormJbkJqzQGhziax5PItDUTMAM9uE2XXQmM37dyd4hVM+5aVl7oVxMVUiVQn2oCQFN/LKCZdvSM0pFRqbSmQ==", + "dev": true, + "license": "MIT" + }, + "node_modules/@types/send": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/@types/send/-/send-1.2.1.tgz", + "integrity": "sha512-arsCikDvlU99zl1g69TcAB3mzZPpxgw0UQnaHeC1Nwb015xp8bknZv5rIfri9xTOcMuaVgvabfIRA7PSZVuZIQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "@types/node": "*" + } + }, + "node_modules/@types/serve-static": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/@types/serve-static/-/serve-static-2.2.0.tgz", + "integrity": "sha512-8mam4H1NHLtu7nmtalF7eyBH14QyOASmcxHhSfEoRyr0nP/YdoesEtU+uSRvMe96TW/HPTtkoKqQLl53N7UXMQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "@types/http-errors": "*", + "@types/node": "*" + } + }, + "node_modules/@types/stack-utils": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/@types/stack-utils/-/stack-utils-2.0.3.tgz", + "integrity": "sha512-9aEbYZ3TbYMznPdcdr3SmIrLXwC/AKZXQeCf9Pgao5CKb8CyHuEX5jzWPTkvregvhRJHcpRO6BFoGW9ycaOkYw==", + "dev": true, + "license": "MIT" + }, + "node_modules/@types/uuid": { + "version": "10.0.0", + "resolved": "https://registry.npmjs.org/@types/uuid/-/uuid-10.0.0.tgz", + "integrity": "sha512-7gqG38EyHgyP1S+7+xomFtL+ZNHcKv6DwNaCZmJmo1vgMugyF3TCnXVg4t1uk89mLNwnLtnY3TpOpCOyp1/xHQ==", + "dev": true, + "license": "MIT" + }, + "node_modules/@types/ws": { + "version": "8.18.1", + "resolved": "https://registry.npmjs.org/@types/ws/-/ws-8.18.1.tgz", + "integrity": "sha512-ThVF6DCVhA8kUGy+aazFQ4kXQ7E1Ty7A3ypFOe0IcJV8O/M511G99AW24irKrW56Wt44yG9+ij8FaqoBGkuBXg==", + "dev": true, + "license": "MIT", + "dependencies": { + "@types/node": "*" + } + }, + "node_modules/@types/yargs": { + "version": "17.0.35", + "resolved": "https://registry.npmjs.org/@types/yargs/-/yargs-17.0.35.tgz", + "integrity": "sha512-qUHkeCyQFxMXg79wQfTtfndEC+N9ZZg76HJftDJp+qH2tV7Gj4OJi7l+PiWwJ+pWtW8GwSmqsDj/oymhrTWXjg==", + "dev": true, + "license": "MIT", + "dependencies": { + "@types/yargs-parser": "*" + } + }, + "node_modules/@types/yargs-parser": { + "version": "21.0.3", + "resolved": "https://registry.npmjs.org/@types/yargs-parser/-/yargs-parser-21.0.3.tgz", + "integrity": "sha512-I4q9QU9MQv4oEOz4tAHJtNz1cwuLxn2F3xcc2iV5WdqLPpUnj30aUuxt1mAxYTG+oe8CZMV/+6rU4S4gRDzqtQ==", + "dev": true, + "license": "MIT" + }, + "node_modules/accepts": { + "version": "1.3.8", + "resolved": "https://registry.npmjs.org/accepts/-/accepts-1.3.8.tgz", + "integrity": "sha512-PYAthTa2m2VKxuvSD3DPC/Gy+U+sOA1LAuT8mkmRuvw+NACSaeXEQ+NHcVF7rONl6qcaxV3Uuemwawk+7+SJLw==", + "license": "MIT", + "dependencies": { + "mime-types": "~2.1.34", + "negotiator": "0.6.3" + }, + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/acorn": { + "version": "8.16.0", + "resolved": "https://registry.npmjs.org/acorn/-/acorn-8.16.0.tgz", + "integrity": "sha512-UVJyE9MttOsBQIDKw1skb9nAwQuR5wuGD3+82K6JgJlm/Y+KI92oNsMNGZCYdDsVtRHSak0pcV5Dno5+4jh9sw==", + "dev": true, + "license": "MIT", + "bin": { + "acorn": "bin/acorn" + }, + "engines": { + "node": ">=0.4.0" + } + }, + "node_modules/acorn-walk": { + "version": "8.3.5", + "resolved": "https://registry.npmjs.org/acorn-walk/-/acorn-walk-8.3.5.tgz", + "integrity": "sha512-HEHNfbars9v4pgpW6SO1KSPkfoS0xVOM/9UzkJltjlsHZmJasxg8aXkuZa7SMf8vKGIBhpUsPluQSqhJFCqebw==", + "dev": true, + "license": "MIT", + "dependencies": { + "acorn": "^8.11.0" + }, + "engines": { + "node": ">=0.4.0" + } + }, + "node_modules/ansi-escapes": { + "version": "4.3.2", + "resolved": "https://registry.npmjs.org/ansi-escapes/-/ansi-escapes-4.3.2.tgz", + "integrity": "sha512-gKXj5ALrKWQLsYG9jlTRmR/xKluxHV+Z9QEwNIgCfM1/uwPMCuzVVnh5mwTd+OuBZcwSIMbqssNWRm1lE51QaQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "type-fest": "^0.21.3" + }, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/ansi-regex": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.1.tgz", + "integrity": "sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=8" + } + }, + "node_modules/ansi-styles": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", + "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", + "dev": true, + "license": "MIT", + "dependencies": { + "color-convert": "^2.0.1" + }, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/chalk/ansi-styles?sponsor=1" + } + }, + "node_modules/anymatch": { + "version": "3.1.3", + "resolved": "https://registry.npmjs.org/anymatch/-/anymatch-3.1.3.tgz", + "integrity": "sha512-KMReFUr0B4t+D+OBkjR3KYqvocp2XaSzO55UcB6mgQMd3KbcE+mWTyvVV7D/zsdEbNnV6acZUutkiHQXvTr1Rw==", + "dev": true, + "license": "ISC", + "dependencies": { + "normalize-path": "^3.0.0", + "picomatch": "^2.0.4" + }, + "engines": { + "node": ">= 8" + } + }, + "node_modules/arg": { + "version": "4.1.3", + "resolved": "https://registry.npmjs.org/arg/-/arg-4.1.3.tgz", + "integrity": "sha512-58S9QDqG0Xx27YwPSt9fJxivjYl432YCwfDMfZ+71RAqUrZef7LrKQZ3LHLOwCS4FLNBplP533Zx895SeOCHvA==", + "dev": true, + "license": "MIT" + }, + "node_modules/argparse": { + "version": "1.0.10", + "resolved": "https://registry.npmjs.org/argparse/-/argparse-1.0.10.tgz", + "integrity": "sha512-o5Roy6tNG4SL/FOkCAN6RzjiakZS25RLYFrcMttJqbdd8BWrnA+fGz57iN5Pb06pvBGvl5gQ0B48dJlslXvoTg==", + "dev": true, + "license": "MIT", + "dependencies": { + "sprintf-js": "~1.0.2" + } + }, + "node_modules/array-flatten": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/array-flatten/-/array-flatten-1.1.1.tgz", + "integrity": "sha512-PCVAQswWemu6UdxsDFFX/+gVeYqKAod3D3UVm91jHwynguOwAvYPhx8nNlM++NqRcK6CxxpUafjmhIdKiHibqg==", + "license": "MIT" + }, + "node_modules/babel-jest": { + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/babel-jest/-/babel-jest-29.7.0.tgz", + "integrity": "sha512-BrvGY3xZSwEcCzKvKsCi2GgHqDqsYkOP4/by5xCgIwGXQxIEh+8ew3gmrE1y7XRR6LHZIj6yLYnUi/mm2KXKBg==", + "dev": true, + "license": "MIT", + "dependencies": { + "@jest/transform": "^29.7.0", + "@types/babel__core": "^7.1.14", + "babel-plugin-istanbul": "^6.1.1", + "babel-preset-jest": "^29.6.3", + "chalk": "^4.0.0", + "graceful-fs": "^4.2.9", + "slash": "^3.0.0" + }, + "engines": { + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + }, + "peerDependencies": { + "@babel/core": "^7.8.0" + } + }, + "node_modules/babel-plugin-istanbul": { + "version": "6.1.1", + "resolved": "https://registry.npmjs.org/babel-plugin-istanbul/-/babel-plugin-istanbul-6.1.1.tgz", + "integrity": "sha512-Y1IQok9821cC9onCx5otgFfRm7Lm+I+wwxOx738M/WLPZ9Q42m4IG5W0FNX8WLL2gYMZo3JkuXIH2DOpWM+qwA==", + "dev": true, + "license": "BSD-3-Clause", + "dependencies": { + "@babel/helper-plugin-utils": "^7.0.0", + "@istanbuljs/load-nyc-config": "^1.0.0", + "@istanbuljs/schema": "^0.1.2", + "istanbul-lib-instrument": "^5.0.4", + "test-exclude": "^6.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/babel-plugin-istanbul/node_modules/istanbul-lib-instrument": { + "version": "5.2.1", + "resolved": "https://registry.npmjs.org/istanbul-lib-instrument/-/istanbul-lib-instrument-5.2.1.tgz", + "integrity": "sha512-pzqtp31nLv/XFOzXGuvhCb8qhjmTVo5vjVk19XE4CRlSWz0KoeJ3bw9XsA7nOp9YBf4qHjwBxkDzKcME/J29Yg==", + "dev": true, + "license": "BSD-3-Clause", + "dependencies": { + "@babel/core": "^7.12.3", + "@babel/parser": "^7.14.7", + "@istanbuljs/schema": "^0.1.2", + "istanbul-lib-coverage": "^3.2.0", + "semver": "^6.3.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/babel-plugin-jest-hoist": { + "version": "29.6.3", + "resolved": "https://registry.npmjs.org/babel-plugin-jest-hoist/-/babel-plugin-jest-hoist-29.6.3.tgz", + "integrity": "sha512-ESAc/RJvGTFEzRwOTT4+lNDk/GNHMkKbNzsvT0qKRfDyyYTskxB5rnU2njIDYVxXCBHHEI1c0YwHob3WaYujOg==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/template": "^7.3.3", + "@babel/types": "^7.3.3", + "@types/babel__core": "^7.1.14", + "@types/babel__traverse": "^7.0.6" + }, + "engines": { + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + } + }, + "node_modules/babel-preset-current-node-syntax": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/babel-preset-current-node-syntax/-/babel-preset-current-node-syntax-1.2.0.tgz", + "integrity": "sha512-E/VlAEzRrsLEb2+dv8yp3bo4scof3l9nR4lrld+Iy5NyVqgVYUJnDAmunkhPMisRI32Qc4iRiz425d8vM++2fg==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/plugin-syntax-async-generators": "^7.8.4", + "@babel/plugin-syntax-bigint": "^7.8.3", + "@babel/plugin-syntax-class-properties": "^7.12.13", + "@babel/plugin-syntax-class-static-block": "^7.14.5", + "@babel/plugin-syntax-import-attributes": "^7.24.7", + "@babel/plugin-syntax-import-meta": "^7.10.4", + "@babel/plugin-syntax-json-strings": "^7.8.3", + "@babel/plugin-syntax-logical-assignment-operators": "^7.10.4", + "@babel/plugin-syntax-nullish-coalescing-operator": "^7.8.3", + "@babel/plugin-syntax-numeric-separator": "^7.10.4", + "@babel/plugin-syntax-object-rest-spread": "^7.8.3", + "@babel/plugin-syntax-optional-catch-binding": "^7.8.3", + "@babel/plugin-syntax-optional-chaining": "^7.8.3", + "@babel/plugin-syntax-private-property-in-object": "^7.14.5", + "@babel/plugin-syntax-top-level-await": "^7.14.5" + }, + "peerDependencies": { + "@babel/core": "^7.0.0 || ^8.0.0-0" + } + }, + "node_modules/babel-preset-jest": { + "version": "29.6.3", + "resolved": "https://registry.npmjs.org/babel-preset-jest/-/babel-preset-jest-29.6.3.tgz", + "integrity": "sha512-0B3bhxR6snWXJZtR/RliHTDPRgn1sNHOR0yVtq/IiQFyuOVjFS+wuio/R4gSNkyYmKmJB4wGZv2NZanmKmTnNA==", + "dev": true, + "license": "MIT", + "dependencies": { + "babel-plugin-jest-hoist": "^29.6.3", + "babel-preset-current-node-syntax": "^1.0.0" + }, + "engines": { + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0" + } + }, + "node_modules/balanced-match": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.2.tgz", + "integrity": "sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw==", + "dev": true, + "license": "MIT" + }, + "node_modules/baseline-browser-mapping": { + "version": "2.10.8", + "resolved": "https://registry.npmjs.org/baseline-browser-mapping/-/baseline-browser-mapping-2.10.8.tgz", + "integrity": "sha512-PCLz/LXGBsNTErbtB6i5u4eLpHeMfi93aUv5duMmj6caNu6IphS4q6UevDnL36sZQv9lrP11dbPKGMaXPwMKfQ==", + "dev": true, + "license": "Apache-2.0", + "bin": { + "baseline-browser-mapping": "dist/cli.cjs" + }, + "engines": { + "node": ">=6.0.0" + } + }, + "node_modules/binary-extensions": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/binary-extensions/-/binary-extensions-2.3.0.tgz", + "integrity": "sha512-Ceh+7ox5qe7LJuLHoY0feh3pHuUDHAcRUeyL2VYghZwfpkNIy/+8Ocg0a3UuSoYzavmylwuLWQOf3hl0jjMMIw==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/body-parser": { + "version": "1.20.4", + "resolved": "https://registry.npmjs.org/body-parser/-/body-parser-1.20.4.tgz", + "integrity": "sha512-ZTgYYLMOXY9qKU/57FAo8F+HA2dGX7bqGc71txDRC1rS4frdFI5R7NhluHxH6M0YItAP0sHB4uqAOcYKxO6uGA==", + "license": "MIT", + "dependencies": { + "bytes": "~3.1.2", + "content-type": "~1.0.5", + "debug": "2.6.9", + "depd": "2.0.0", + "destroy": "~1.2.0", + "http-errors": "~2.0.1", + "iconv-lite": "~0.4.24", + "on-finished": "~2.4.1", + "qs": "~6.14.0", + "raw-body": "~2.5.3", + "type-is": "~1.6.18", + "unpipe": "~1.0.0" + }, + "engines": { + "node": ">= 0.8", + "npm": "1.2.8000 || >= 1.4.16" + } + }, + "node_modules/brace-expansion": { + "version": "1.1.12", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.12.tgz", + "integrity": "sha512-9T9UjW3r0UW5c1Q7GTwllptXwhvYmEzFhzMfZ9H7FQWt+uZePjZPjBP/W1ZEyZ1twGWom5/56TF4lPcqjnDHcg==", + "dev": true, + "license": "MIT", + "dependencies": { + "balanced-match": "^1.0.0", + "concat-map": "0.0.1" + } + }, + "node_modules/braces": { + "version": "3.0.3", + "resolved": "https://registry.npmjs.org/braces/-/braces-3.0.3.tgz", + "integrity": "sha512-yQbXgO/OSZVD2IsiLlro+7Hf6Q18EJrKSEsdoMzKePKXct3gvD8oLcOQdIzGupr5Fj+EDe8gO/lxc1BzfMpxvA==", + "dev": true, + "license": "MIT", + "dependencies": { + "fill-range": "^7.1.1" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/browserslist": { + "version": "4.28.1", + "resolved": "https://registry.npmjs.org/browserslist/-/browserslist-4.28.1.tgz", + "integrity": "sha512-ZC5Bd0LgJXgwGqUknZY/vkUQ04r8NXnJZ3yYi4vDmSiZmC/pdSN0NbNRPxZpbtO4uAfDUAFffO8IZoM3Gj8IkA==", + "dev": true, + "funding": [ + { + "type": "opencollective", + "url": "https://opencollective.com/browserslist" + }, + { + "type": "tidelift", + "url": "https://tidelift.com/funding/github/npm/browserslist" + }, + { + "type": "github", + "url": "https://github.com/sponsors/ai" + } + ], + "license": "MIT", + "peer": true, + "dependencies": { + "baseline-browser-mapping": "^2.9.0", + "caniuse-lite": "^1.0.30001759", + "electron-to-chromium": "^1.5.263", + "node-releases": "^2.0.27", + "update-browserslist-db": "^1.2.0" + }, + "bin": { + "browserslist": "cli.js" + }, + "engines": { + "node": "^6 || ^7 || ^8 || ^9 || ^10 || ^11 || ^12 || >=13.7" + } + }, + "node_modules/bs-logger": { + "version": "0.2.6", + "resolved": "https://registry.npmjs.org/bs-logger/-/bs-logger-0.2.6.tgz", + "integrity": "sha512-pd8DCoxmbgc7hyPKOvxtqNcjYoOsABPQdcCUjGp3d42VR2CX1ORhk2A87oqqu5R1kk+76nsxZupkmyd+MVtCog==", + "dev": true, + "license": "MIT", + "dependencies": { + "fast-json-stable-stringify": "2.x" + }, + "engines": { + "node": ">= 6" + } + }, + "node_modules/bser": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/bser/-/bser-2.1.1.tgz", + "integrity": "sha512-gQxTNE/GAfIIrmHLUE3oJyp5FO6HRBfhjnw4/wMmA63ZGDJnWBmgY/lyQBpnDUkGmAhbSe39tx2d/iTOAfglwQ==", + "dev": true, + "license": "Apache-2.0", + "dependencies": { + "node-int64": "^0.4.0" + } + }, + "node_modules/buffer-from": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/buffer-from/-/buffer-from-1.1.2.tgz", + "integrity": "sha512-E+XQCRwSbaaiChtv6k6Dwgc+bx+Bs6vuKJHHl5kox/BaKbhiXzqQOwK4cO22yElGp2OCmjwVhT3HmxgyPGnJfQ==", + "dev": true, + "license": "MIT" + }, + "node_modules/bytes": { + "version": "3.1.2", + "resolved": "https://registry.npmjs.org/bytes/-/bytes-3.1.2.tgz", + "integrity": "sha512-/Nf7TyzTx6S3yRJObOAV7956r8cr2+Oj8AC5dt8wSP3BQAoeX58NoHyCU8P8zGkNXStjTSi6fzO6F0pBdcYbEg==", + "license": "MIT", + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/call-bind-apply-helpers": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/call-bind-apply-helpers/-/call-bind-apply-helpers-1.0.2.tgz", + "integrity": "sha512-Sp1ablJ0ivDkSzjcaJdxEunN5/XvksFJ2sMBFfq6x0ryhQV/2b/KwFe21cMpmHtPOSij8K99/wSfoEuTObmuMQ==", + "license": "MIT", + "dependencies": { + "es-errors": "^1.3.0", + "function-bind": "^1.1.2" + }, + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/call-bound": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/call-bound/-/call-bound-1.0.4.tgz", + "integrity": "sha512-+ys997U96po4Kx/ABpBCqhA9EuxJaQWDQg7295H4hBphv3IZg0boBKuwYpt4YXp6MZ5AmZQnU/tyMTlRpaSejg==", + "license": "MIT", + "dependencies": { + "call-bind-apply-helpers": "^1.0.2", + "get-intrinsic": "^1.3.0" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/callsites": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/callsites/-/callsites-3.1.0.tgz", + "integrity": "sha512-P8BjAsXvZS+VIDUI11hHCQEv74YT67YUi5JJFNWIqL235sBmjX4+qx9Muvls5ivyNENctx46xQLQ3aTuE7ssaQ==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=6" + } + }, + "node_modules/camelcase": { + "version": "5.3.1", + "resolved": "https://registry.npmjs.org/camelcase/-/camelcase-5.3.1.tgz", + "integrity": "sha512-L28STB170nwWS63UjtlEOE3dldQApaJXZkOI1uMFfzf3rRuPegHaHesyee+YxQ+W6SvRDQV6UrdOdRiR153wJg==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=6" + } + }, + "node_modules/caniuse-lite": { + "version": "1.0.30001780", + "resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001780.tgz", + "integrity": "sha512-llngX0E7nQci5BPJDqoZSbuZ5Bcs9F5db7EtgfwBerX9XGtkkiO4NwfDDIRzHTTwcYC8vC7bmeUEPGrKlR/TkQ==", + "dev": true, + "funding": [ + { + "type": "opencollective", + "url": "https://opencollective.com/browserslist" + }, + { + "type": "tidelift", + "url": "https://tidelift.com/funding/github/npm/caniuse-lite" + }, + { + "type": "github", + "url": "https://github.com/sponsors/ai" + } + ], + "license": "CC-BY-4.0" + }, + "node_modules/chalk": { + "version": "4.1.2", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", + "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", + "dev": true, + "license": "MIT", + "dependencies": { + "ansi-styles": "^4.1.0", + "supports-color": "^7.1.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/chalk/chalk?sponsor=1" + } + }, + "node_modules/char-regex": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/char-regex/-/char-regex-1.0.2.tgz", + "integrity": "sha512-kWWXztvZ5SBQV+eRgKFeh8q5sLuZY2+8WUIzlxWVTg+oGwY14qylx1KbKzHd8P6ZYkAg0xyIDU9JMHhyJMZ1jw==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=10" + } + }, + "node_modules/chokidar": { + "version": "3.6.0", + "resolved": "https://registry.npmjs.org/chokidar/-/chokidar-3.6.0.tgz", + "integrity": "sha512-7VT13fmjotKpGipCW9JEQAusEPE+Ei8nl6/g4FBAmIm0GOOLMua9NDDo/DWp0ZAxCr3cPq5ZpBqmPAQgDda2Pw==", + "dev": true, + "license": "MIT", + "dependencies": { + "anymatch": "~3.1.2", + "braces": "~3.0.2", + "glob-parent": "~5.1.2", + "is-binary-path": "~2.1.0", + "is-glob": "~4.0.1", + "normalize-path": "~3.0.0", + "readdirp": "~3.6.0" + }, + "engines": { + "node": ">= 8.10.0" + }, + "funding": { + "url": "https://paulmillr.com/funding/" + }, + "optionalDependencies": { + "fsevents": "~2.3.2" + } + }, + "node_modules/ci-info": { + "version": "3.9.0", + "resolved": "https://registry.npmjs.org/ci-info/-/ci-info-3.9.0.tgz", + "integrity": "sha512-NIxF55hv4nSqQswkAeiOi1r83xy8JldOFDTWiug55KBu9Jnblncd2U6ViHmYgHf01TPZS77NJBhBMKdWj9HQMQ==", + "dev": true, + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/sibiraj-s" + } + ], + "license": "MIT", + "engines": { + "node": ">=8" + } + }, + "node_modules/cjs-module-lexer": { + "version": "1.4.3", + "resolved": "https://registry.npmjs.org/cjs-module-lexer/-/cjs-module-lexer-1.4.3.tgz", + "integrity": "sha512-9z8TZaGM1pfswYeXrUpzPrkx8UnWYdhJclsiYMm6x/w5+nN+8Tf/LnAgfLGQCm59qAOxU8WwHEq2vNwF6i4j+Q==", + "dev": true, + "license": "MIT" + }, + "node_modules/cliui": { + "version": "8.0.1", + "resolved": "https://registry.npmjs.org/cliui/-/cliui-8.0.1.tgz", + "integrity": "sha512-BSeNnyus75C4//NQ9gQt1/csTXyo/8Sb+afLAkzAptFuMsod9HFokGNudZpi/oQV73hnVK+sR+5PVRMd+Dr7YQ==", + "dev": true, + "license": "ISC", + "dependencies": { + "string-width": "^4.2.0", + "strip-ansi": "^6.0.1", + "wrap-ansi": "^7.0.0" + }, + "engines": { + "node": ">=12" + } + }, + "node_modules/co": { + "version": "4.6.0", + "resolved": "https://registry.npmjs.org/co/-/co-4.6.0.tgz", + "integrity": "sha512-QVb0dM5HvG+uaxitm8wONl7jltx8dqhfU33DcqtOZcLSVIKSDDLDi7+0LbAKiyI8hD9u42m2YxXSkMGWThaecQ==", + "dev": true, + "license": "MIT", + "engines": { + "iojs": ">= 1.0.0", + "node": ">= 0.12.0" + } + }, + "node_modules/collect-v8-coverage": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/collect-v8-coverage/-/collect-v8-coverage-1.0.3.tgz", + "integrity": "sha512-1L5aqIkwPfiodaMgQunkF1zRhNqifHBmtbbbxcr6yVxxBnliw4TDOW6NxpO8DJLgJ16OT+Y4ztZqP6p/FtXnAw==", + "dev": true, + "license": "MIT" + }, + "node_modules/color-convert": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", + "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "color-name": "~1.1.4" + }, + "engines": { + "node": ">=7.0.0" + } + }, + "node_modules/color-name": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", + "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==", + "dev": true, + "license": "MIT" + }, + "node_modules/concat-map": { + "version": "0.0.1", + "resolved": "https://registry.npmjs.org/concat-map/-/concat-map-0.0.1.tgz", + "integrity": "sha512-/Srv4dswyQNBfohGpz9o6Yb3Gz3SrUDqBH5rTuhGR7ahtlbYKnVxw2bCFMRljaA7EXHaXZ8wsHdodFvbkhKmqg==", + "dev": true, + "license": "MIT" + }, + "node_modules/content-disposition": { + "version": "0.5.4", + "resolved": "https://registry.npmjs.org/content-disposition/-/content-disposition-0.5.4.tgz", + "integrity": "sha512-FveZTNuGw04cxlAiWbzi6zTAL/lhehaWbTtgluJh4/E95DqMwTmha3KZN1aAWA8cFIhHzMZUvLevkw5Rqk+tSQ==", + "license": "MIT", + "dependencies": { + "safe-buffer": "5.2.1" + }, + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/content-type": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/content-type/-/content-type-1.0.5.tgz", + "integrity": "sha512-nTjqfcBFEipKdXCv4YDQWCfmcLZKm81ldF0pAopTvyrFGVbcR6P/VAAd5G7N+0tTr8QqiU0tFadD6FK4NtJwOA==", + "license": "MIT", + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/convert-source-map": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/convert-source-map/-/convert-source-map-2.0.0.tgz", + "integrity": "sha512-Kvp459HrV2FEJ1CAsi1Ku+MY3kasH19TFykTz2xWmMeq6bk2NU3XXvfJ+Q61m0xktWwt+1HSYf3JZsTms3aRJg==", + "dev": true, + "license": "MIT" + }, + "node_modules/cookie": { + "version": "0.7.2", + "resolved": "https://registry.npmjs.org/cookie/-/cookie-0.7.2.tgz", + "integrity": "sha512-yki5XnKuf750l50uGTllt6kKILY4nQ1eNIQatoXEByZ5dWgnKqbnqmTrBE5B4N7lrMJKQ2ytWMiTO2o0v6Ew/w==", + "license": "MIT", + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/cookie-signature": { + "version": "1.0.7", + "resolved": "https://registry.npmjs.org/cookie-signature/-/cookie-signature-1.0.7.tgz", + "integrity": "sha512-NXdYc3dLr47pBkpUCHtKSwIOQXLVn8dZEuywboCOJY/osA0wFSLlSawr3KN8qXJEyX66FcONTH8EIlVuK0yyFA==", + "license": "MIT" + }, + "node_modules/cors": { + "version": "2.8.6", + "resolved": "https://registry.npmjs.org/cors/-/cors-2.8.6.tgz", + "integrity": "sha512-tJtZBBHA6vjIAaF6EnIaq6laBBP9aq/Y3ouVJjEfoHbRBcHBAHYcMh/w8LDrk2PvIMMq8gmopa5D4V8RmbrxGw==", + "license": "MIT", + "dependencies": { + "object-assign": "^4", + "vary": "^1" + }, + "engines": { + "node": ">= 0.10" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/express" + } + }, + "node_modules/create-jest": { + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/create-jest/-/create-jest-29.7.0.tgz", + "integrity": "sha512-Adz2bdH0Vq3F53KEMJOoftQFutWCukm6J24wbPWRO4k1kMY7gS7ds/uoJkNuV8wDCtWWnuwGcJwpWcih+zEW1Q==", + "dev": true, + "license": "MIT", + "dependencies": { + "@jest/types": "^29.6.3", + "chalk": "^4.0.0", + "exit": "^0.1.2", + "graceful-fs": "^4.2.9", + "jest-config": "^29.7.0", + "jest-util": "^29.7.0", + "prompts": "^2.0.1" + }, + "bin": { + "create-jest": "bin/create-jest.js" + }, + "engines": { + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + } + }, + "node_modules/create-require": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/create-require/-/create-require-1.1.1.tgz", + "integrity": "sha512-dcKFX3jn0MpIaXjisoRvexIJVEKzaq7z2rZKxf+MSr9TkdmHmsU4m2lcLojrj/FHl8mk5VxMmYA+ftRkP/3oKQ==", + "dev": true, + "license": "MIT" + }, + "node_modules/cross-spawn": { + "version": "7.0.6", + "resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-7.0.6.tgz", + "integrity": "sha512-uV2QOWP2nWzsy2aMp8aRibhi9dlzF5Hgh5SHaB9OiTGEyDTiJJyx0uy51QXdyWbtAHNua4XJzUKca3OzKUd3vA==", + "dev": true, + "license": "MIT", + "dependencies": { + "path-key": "^3.1.0", + "shebang-command": "^2.0.0", + "which": "^2.0.1" + }, + "engines": { + "node": ">= 8" + } + }, + "node_modules/debug": { + "version": "2.6.9", + "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", + "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", + "license": "MIT", + "dependencies": { + "ms": "2.0.0" + } + }, + "node_modules/dedent": { + "version": "1.7.2", + "resolved": "https://registry.npmjs.org/dedent/-/dedent-1.7.2.tgz", + "integrity": "sha512-WzMx3mW98SN+zn3hgemf4OzdmyNhhhKz5Ay0pUfQiMQ3e1g+xmTJWp/pKdwKVXhdSkAEGIIzqeuWrL3mV/AXbA==", + "dev": true, + "license": "MIT", + "peerDependencies": { + "babel-plugin-macros": "^3.1.0" + }, + "peerDependenciesMeta": { + "babel-plugin-macros": { + "optional": true + } + } + }, + "node_modules/deepmerge": { + "version": "4.3.1", + "resolved": "https://registry.npmjs.org/deepmerge/-/deepmerge-4.3.1.tgz", + "integrity": "sha512-3sUqbMEc77XqpdNO7FRyRog+eW3ph+GYCbj+rK+uYyRMuwsVy0rMiVtPn+QJlKFvWP/1PYpapqYn0Me2knFn+A==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/depd": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/depd/-/depd-2.0.0.tgz", + "integrity": "sha512-g7nH6P6dyDioJogAAGprGpCtVImJhpPk/roCzdb3fIh61/s/nPsfR6onyMwkCAR/OlC3yBC0lESvUoQEAssIrw==", + "license": "MIT", + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/destroy": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/destroy/-/destroy-1.2.0.tgz", + "integrity": "sha512-2sJGJTaXIIaR1w4iJSNoN0hnMY7Gpc/n8D4qSCJw8QqFWXf7cuAgnEHxBpweaVcPevC2l3KpjYCx3NypQQgaJg==", + "license": "MIT", + "engines": { + "node": ">= 0.8", + "npm": "1.2.8000 || >= 1.4.16" + } + }, + "node_modules/detect-newline": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/detect-newline/-/detect-newline-3.1.0.tgz", + "integrity": "sha512-TLz+x/vEXm/Y7P7wn1EJFNLxYpUD4TgMosxY6fAVJUnJMbupHBOncxyWUG9OpTaH9EBD7uFI5LfEgmMOc54DsA==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=8" + } + }, + "node_modules/diff": { + "version": "4.0.4", + "resolved": "https://registry.npmjs.org/diff/-/diff-4.0.4.tgz", + "integrity": "sha512-X07nttJQkwkfKfvTPG/KSnE2OMdcUCao6+eXF3wmnIQRn2aPAHH3VxDbDOdegkd6JbPsXqShpvEOHfAT+nCNwQ==", + "dev": true, + "license": "BSD-3-Clause", + "engines": { + "node": ">=0.3.1" + } + }, + "node_modules/diff-sequences": { + "version": "29.6.3", + "resolved": "https://registry.npmjs.org/diff-sequences/-/diff-sequences-29.6.3.tgz", + "integrity": "sha512-EjePK1srD3P08o2j4f0ExnylqRs5B9tJjcp9t1krH2qRi8CCdsYfwe9JgSLurFBWwq4uOlipzfk5fHNvwFKr8Q==", + "dev": true, + "license": "MIT", + "engines": { + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + } + }, + "node_modules/dotenv": { + "version": "16.6.1", + "resolved": "https://registry.npmjs.org/dotenv/-/dotenv-16.6.1.tgz", + "integrity": "sha512-uBq4egWHTcTt33a72vpSG0z3HnPuIl6NqYcTrKEg2azoEyl2hpW0zqlxysq2pK9HlDIHyHyakeYaYnSAwd8bow==", + "license": "BSD-2-Clause", + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://dotenvx.com" + } + }, + "node_modules/dunder-proto": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/dunder-proto/-/dunder-proto-1.0.1.tgz", + "integrity": "sha512-KIN/nDJBQRcXw0MLVhZE9iQHmG68qAVIBg9CqmUYjmQIhgij9U5MFvrqkUL5FbtyyzZuOeOt0zdeRe4UY7ct+A==", + "license": "MIT", + "dependencies": { + "call-bind-apply-helpers": "^1.0.1", + "es-errors": "^1.3.0", + "gopd": "^1.2.0" + }, + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/ee-first": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/ee-first/-/ee-first-1.1.1.tgz", + "integrity": "sha512-WMwm9LhRUo+WUaRN+vRuETqG89IgZphVSNkdFgeb6sS/E4OrDIN7t48CAewSHXc6C8lefD8KKfr5vY61brQlow==", + "license": "MIT" + }, + "node_modules/electron-to-chromium": { + "version": "1.5.313", + "resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.5.313.tgz", + "integrity": "sha512-QBMrTWEf00GXZmJyx2lbYD45jpI3TUFnNIzJ5BBc8piGUDwMPa1GV6HJWTZVvY/eiN3fSopl7NRbgGp9sZ9LTA==", + "dev": true, + "license": "ISC" + }, + "node_modules/emittery": { + "version": "0.13.1", + "resolved": "https://registry.npmjs.org/emittery/-/emittery-0.13.1.tgz", + "integrity": "sha512-DeWwawk6r5yR9jFgnDKYt4sLS0LmHJJi3ZOnb5/JdbYwj3nW+FxQnHIjhBKz8YLC7oRNPVM9NQ47I3CVx34eqQ==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/sindresorhus/emittery?sponsor=1" + } + }, + "node_modules/emoji-regex": { + "version": "8.0.0", + "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-8.0.0.tgz", + "integrity": "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==", + "dev": true, + "license": "MIT" + }, + "node_modules/encodeurl": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/encodeurl/-/encodeurl-2.0.0.tgz", + "integrity": "sha512-Q0n9HRi4m6JuGIV1eFlmvJB7ZEVxu93IrMyiMsGC0lrMJMWzRgx6WGquyfQgZVb31vhGgXnfmPNNXmxnOkRBrg==", + "license": "MIT", + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/error-ex": { + "version": "1.3.4", + "resolved": "https://registry.npmjs.org/error-ex/-/error-ex-1.3.4.tgz", + "integrity": "sha512-sqQamAnR14VgCr1A618A3sGrygcpK+HEbenA/HiEAkkUwcZIIB/tgWqHFxWgOyDh4nB4JCRimh79dR5Ywc9MDQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "is-arrayish": "^0.2.1" + } + }, + "node_modules/es-define-property": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/es-define-property/-/es-define-property-1.0.1.tgz", + "integrity": "sha512-e3nRfgfUZ4rNGL232gUgX06QNyyez04KdjFrF+LTRoOXmrOgFKDg4BCdsjW8EnT69eqdYGmRpJwiPVYNrCaW3g==", + "license": "MIT", + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/es-errors": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/es-errors/-/es-errors-1.3.0.tgz", + "integrity": "sha512-Zf5H2Kxt2xjTvbJvP2ZWLEICxA6j+hAmMzIlypy4xcBg1vKVnx89Wy0GbS+kf5cwCVFFzdCFh2XSCFNULS6csw==", + "license": "MIT", + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/es-object-atoms": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/es-object-atoms/-/es-object-atoms-1.1.1.tgz", + "integrity": "sha512-FGgH2h8zKNim9ljj7dankFPcICIK9Cp5bm+c2gQSYePhpaG5+esrLODihIorn+Pe6FGJzWhXQotPv73jTaldXA==", + "license": "MIT", + "dependencies": { + "es-errors": "^1.3.0" + }, + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/escalade": { + "version": "3.2.0", + "resolved": "https://registry.npmjs.org/escalade/-/escalade-3.2.0.tgz", + "integrity": "sha512-WUj2qlxaQtO4g6Pq5c29GTcWGDyd8itL8zTlipgECz3JesAiiOKotd8JU6otB3PACgG6xkJUyVhboMS+bje/jA==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=6" + } + }, + "node_modules/escape-html": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/escape-html/-/escape-html-1.0.3.tgz", + "integrity": "sha512-NiSupZ4OeuGwr68lGIeym/ksIZMJodUGOSCZ/FSnTxcrekbvqrgdUxlJOMpijaKZVjAJrWrGs/6Jy8OMuyj9ow==", + "license": "MIT" + }, + "node_modules/escape-string-regexp": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-2.0.0.tgz", + "integrity": "sha512-UpzcLCXolUWcNu5HtVMHYdXJjArjsF9C0aNnquZYY4uW/Vu0miy5YoWvbV345HauVvcAUnpRuhMMcqTcGOY2+w==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=8" + } + }, + "node_modules/esprima": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/esprima/-/esprima-4.0.1.tgz", + "integrity": "sha512-eGuFFw7Upda+g4p+QHvnW0RyTX/SVeJBDM/gCtMARO0cLuT2HcEKnTPvhjV6aGeqrCB/sbNop0Kszm0jsaWU4A==", + "dev": true, + "license": "BSD-2-Clause", + "bin": { + "esparse": "bin/esparse.js", + "esvalidate": "bin/esvalidate.js" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/etag": { + "version": "1.8.1", + "resolved": "https://registry.npmjs.org/etag/-/etag-1.8.1.tgz", + "integrity": "sha512-aIL5Fx7mawVa300al2BnEE4iNvo1qETxLrPI/o05L7z6go7fCw1J6EQmbK4FmJ2AS7kgVF/KEZWufBfdClMcPg==", + "license": "MIT", + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/execa": { + "version": "5.1.1", + "resolved": "https://registry.npmjs.org/execa/-/execa-5.1.1.tgz", + "integrity": "sha512-8uSpZZocAZRBAPIEINJj3Lo9HyGitllczc27Eh5YYojjMFMn8yHMDMaUHE2Jqfq05D/wucwI4JGURyXt1vchyg==", + "dev": true, + "license": "MIT", + "dependencies": { + "cross-spawn": "^7.0.3", + "get-stream": "^6.0.0", + "human-signals": "^2.1.0", + "is-stream": "^2.0.0", + "merge-stream": "^2.0.0", + "npm-run-path": "^4.0.1", + "onetime": "^5.1.2", + "signal-exit": "^3.0.3", + "strip-final-newline": "^2.0.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sindresorhus/execa?sponsor=1" + } + }, + "node_modules/exit": { + "version": "0.1.2", + "resolved": "https://registry.npmjs.org/exit/-/exit-0.1.2.tgz", + "integrity": "sha512-Zk/eNKV2zbjpKzrsQ+n1G6poVbErQxJ0LBOJXaKZ1EViLzH+hrLu9cdXI4zw9dBQJslwBEpbQ2P1oS7nDxs6jQ==", + "dev": true, + "engines": { + "node": ">= 0.8.0" + } + }, + "node_modules/expect": { + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/expect/-/expect-29.7.0.tgz", + "integrity": "sha512-2Zks0hf1VLFYI1kbh0I5jP3KHHyCHpkfyHBzsSXRFgl/Bg9mWYfMW8oD+PdMPlEwy5HNsR9JutYy6pMeOh61nw==", + "dev": true, + "license": "MIT", + "dependencies": { + "@jest/expect-utils": "^29.7.0", + "jest-get-type": "^29.6.3", + "jest-matcher-utils": "^29.7.0", + "jest-message-util": "^29.7.0", + "jest-util": "^29.7.0" + }, + "engines": { + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + } + }, + "node_modules/express": { + "version": "4.22.1", + "resolved": "https://registry.npmjs.org/express/-/express-4.22.1.tgz", + "integrity": "sha512-F2X8g9P1X7uCPZMA3MVf9wcTqlyNp7IhH5qPCI0izhaOIYXaW9L535tGA3qmjRzpH+bZczqq7hVKxTR4NWnu+g==", + "license": "MIT", + "dependencies": { + "accepts": "~1.3.8", + "array-flatten": "1.1.1", + "body-parser": "~1.20.3", + "content-disposition": "~0.5.4", + "content-type": "~1.0.4", + "cookie": "~0.7.1", + "cookie-signature": "~1.0.6", + "debug": "2.6.9", + "depd": "2.0.0", + "encodeurl": "~2.0.0", + "escape-html": "~1.0.3", + "etag": "~1.8.1", + "finalhandler": "~1.3.1", + "fresh": "~0.5.2", + "http-errors": "~2.0.0", + "merge-descriptors": "1.0.3", + "methods": "~1.1.2", + "on-finished": "~2.4.1", + "parseurl": "~1.3.3", + "path-to-regexp": "~0.1.12", + "proxy-addr": "~2.0.7", + "qs": "~6.14.0", + "range-parser": "~1.2.1", + "safe-buffer": "5.2.1", + "send": "~0.19.0", + "serve-static": "~1.16.2", + "setprototypeof": "1.2.0", + "statuses": "~2.0.1", + "type-is": "~1.6.18", + "utils-merge": "1.0.1", + "vary": "~1.1.2" + }, + "engines": { + "node": ">= 0.10.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/express" + } + }, + "node_modules/fast-json-stable-stringify": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/fast-json-stable-stringify/-/fast-json-stable-stringify-2.1.0.tgz", + "integrity": "sha512-lhd/wF+Lk98HZoTCtlVraHtfh5XYijIjalXck7saUtuanSDyLMxnHhSXEDJqHxD7msR8D0uCmqlkwjCV8xvwHw==", + "dev": true, + "license": "MIT" + }, + "node_modules/fb-watchman": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/fb-watchman/-/fb-watchman-2.0.2.tgz", + "integrity": "sha512-p5161BqbuCaSnB8jIbzQHOlpgsPmK5rJVDfDKO91Axs5NC1uu3HRQm6wt9cd9/+GtQQIO53JdGXXoyDpTAsgYA==", + "dev": true, + "license": "Apache-2.0", + "dependencies": { + "bser": "2.1.1" + } + }, + "node_modules/fill-range": { + "version": "7.1.1", + "resolved": "https://registry.npmjs.org/fill-range/-/fill-range-7.1.1.tgz", + "integrity": "sha512-YsGpe3WHLK8ZYi4tWDg2Jy3ebRz2rXowDxnld4bkQB00cc/1Zw9AWnC0i9ztDJitivtQvaI9KaLyKrc+hBW0yg==", + "dev": true, + "license": "MIT", + "dependencies": { + "to-regex-range": "^5.0.1" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/finalhandler": { + "version": "1.3.2", + "resolved": "https://registry.npmjs.org/finalhandler/-/finalhandler-1.3.2.tgz", + "integrity": "sha512-aA4RyPcd3badbdABGDuTXCMTtOneUCAYH/gxoYRTZlIJdF0YPWuGqiAsIrhNnnqdXGswYk6dGujem4w80UJFhg==", + "license": "MIT", + "dependencies": { + "debug": "2.6.9", + "encodeurl": "~2.0.0", + "escape-html": "~1.0.3", + "on-finished": "~2.4.1", + "parseurl": "~1.3.3", + "statuses": "~2.0.2", + "unpipe": "~1.0.0" + }, + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/find-up": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/find-up/-/find-up-4.1.0.tgz", + "integrity": "sha512-PpOwAdQ/YlXQ2vj8a3h8IipDuYRi3wceVQQGYWxNINccq40Anw7BlsEXCMbt1Zt+OLA6Fq9suIpIWD0OsnISlw==", + "dev": true, + "license": "MIT", + "dependencies": { + "locate-path": "^5.0.0", + "path-exists": "^4.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/forwarded": { + "version": "0.2.0", + "resolved": "https://registry.npmjs.org/forwarded/-/forwarded-0.2.0.tgz", + "integrity": "sha512-buRG0fpBtRHSTCOASe6hD258tEubFoRLb4ZNA6NxMVHNw2gOcwHo9wyablzMzOA5z9xA9L1KNjk/Nt6MT9aYow==", + "license": "MIT", + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/fresh": { + "version": "0.5.2", + "resolved": "https://registry.npmjs.org/fresh/-/fresh-0.5.2.tgz", + "integrity": "sha512-zJ2mQYM18rEFOudeV4GShTGIQ7RbzA7ozbU9I/XBpm7kqgMywgmylMwXHxZJmkVoYkna9d2pVXVXPdYTP9ej8Q==", + "license": "MIT", + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/fs.realpath": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/fs.realpath/-/fs.realpath-1.0.0.tgz", + "integrity": "sha512-OO0pH2lK6a0hZnAdau5ItzHPI6pUlvI7jMVnxUQRtw4owF2wk8lOSabtGDCTP4Ggrg2MbGnWO9X8K1t4+fGMDw==", + "dev": true, + "license": "ISC" + }, + "node_modules/fsevents": { + "version": "2.3.3", + "resolved": "https://registry.npmjs.org/fsevents/-/fsevents-2.3.3.tgz", + "integrity": "sha512-5xoDfX+fL7faATnagmWPpbFtwh/R77WmMMqqHGS65C3vvB0YHrgF+B1YmZ3441tMj5n63k0212XNoJwzlhffQw==", + "dev": true, + "hasInstallScript": true, + "license": "MIT", + "optional": true, + "os": [ + "darwin" + ], + "engines": { + "node": "^8.16.0 || ^10.6.0 || >=11.0.0" + } + }, + "node_modules/function-bind": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/function-bind/-/function-bind-1.1.2.tgz", + "integrity": "sha512-7XHNxH7qX9xG5mIwxkhumTox/MIRNcOgDrxWsMt2pAr23WHp6MrRlN7FBSFpCpr+oVO0F744iUgR82nJMfG2SA==", + "license": "MIT", + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/gensync": { + "version": "1.0.0-beta.2", + "resolved": "https://registry.npmjs.org/gensync/-/gensync-1.0.0-beta.2.tgz", + "integrity": "sha512-3hN7NaskYvMDLQY55gnW3NQ+mesEAepTqlg+VEbj7zzqEMBVNhzcGYYeqFo/TlYz6eQiFcp1HcsCZO+nGgS8zg==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/get-caller-file": { + "version": "2.0.5", + "resolved": "https://registry.npmjs.org/get-caller-file/-/get-caller-file-2.0.5.tgz", + "integrity": "sha512-DyFP3BM/3YHTQOCUL/w0OZHR0lpKeGrxotcHWcqNEdnltqFwXVfhEBQ94eIo34AfQpo0rGki4cyIiftY06h2Fg==", + "dev": true, + "license": "ISC", + "engines": { + "node": "6.* || 8.* || >= 10.*" + } + }, + "node_modules/get-intrinsic": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/get-intrinsic/-/get-intrinsic-1.3.0.tgz", + "integrity": "sha512-9fSjSaos/fRIVIp+xSJlE6lfwhES7LNtKaCBIamHsjr2na1BiABJPo0mOjjz8GJDURarmCPGqaiVg5mfjb98CQ==", + "license": "MIT", + "dependencies": { + "call-bind-apply-helpers": "^1.0.2", + "es-define-property": "^1.0.1", + "es-errors": "^1.3.0", + "es-object-atoms": "^1.1.1", + "function-bind": "^1.1.2", + "get-proto": "^1.0.1", + "gopd": "^1.2.0", + "has-symbols": "^1.1.0", + "hasown": "^2.0.2", + "math-intrinsics": "^1.1.0" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/get-package-type": { + "version": "0.1.0", + "resolved": "https://registry.npmjs.org/get-package-type/-/get-package-type-0.1.0.tgz", + "integrity": "sha512-pjzuKtY64GYfWizNAJ0fr9VqttZkNiK2iS430LtIHzjBEr6bX8Am2zm4sW4Ro5wjWW5cAlRL1qAMTcXbjNAO2Q==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=8.0.0" + } + }, + "node_modules/get-proto": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/get-proto/-/get-proto-1.0.1.tgz", + "integrity": "sha512-sTSfBjoXBp89JvIKIefqw7U2CCebsc74kiY6awiGogKtoSGbgjYE/G/+l9sF3MWFPNc9IcoOC4ODfKHfxFmp0g==", + "license": "MIT", + "dependencies": { + "dunder-proto": "^1.0.1", + "es-object-atoms": "^1.0.0" + }, + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/get-stream": { + "version": "6.0.1", + "resolved": "https://registry.npmjs.org/get-stream/-/get-stream-6.0.1.tgz", + "integrity": "sha512-ts6Wi+2j3jQjqi70w5AlN8DFnkSwC+MqmxEzdEALB2qXZYV3X/b1CTfgPLGJNMeAWxdPfU8FO1ms3NUfaHCPYg==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/glob": { + "version": "7.2.3", + "resolved": "https://registry.npmjs.org/glob/-/glob-7.2.3.tgz", + "integrity": "sha512-nFR0zLpU2YCaRxwoCJvL6UvCH2JFyFVIvwTLsIf21AuHlMskA1hhTdk+LlYJtOlYt9v6dvszD2BGRqBL+iQK9Q==", + "deprecated": "Old versions of glob are not supported, and contain widely publicized security vulnerabilities, which have been fixed in the current version. Please update. Support for old versions may be purchased (at exorbitant rates) by contacting i@izs.me", + "dev": true, + "license": "ISC", + "dependencies": { + "fs.realpath": "^1.0.0", + "inflight": "^1.0.4", + "inherits": "2", + "minimatch": "^3.1.1", + "once": "^1.3.0", + "path-is-absolute": "^1.0.0" + }, + "engines": { + "node": "*" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, + "node_modules/glob-parent": { + "version": "5.1.2", + "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-5.1.2.tgz", + "integrity": "sha512-AOIgSQCepiJYwP3ARnGx+5VnTu2HBYdzbGP45eLw1vr3zB3vZLeyed1sC9hnbcOc9/SrMyM5RPQrkGz4aS9Zow==", + "dev": true, + "license": "ISC", + "dependencies": { + "is-glob": "^4.0.1" + }, + "engines": { + "node": ">= 6" + } + }, + "node_modules/gopd": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/gopd/-/gopd-1.2.0.tgz", + "integrity": "sha512-ZUKRh6/kUFoAiTAtTYPZJ3hw9wNxx+BIBOijnlG9PnrJsCcSjs1wyyD6vJpaYtgnzDrKYRSqf3OO6Rfa93xsRg==", + "license": "MIT", + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/graceful-fs": { + "version": "4.2.11", + "resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.2.11.tgz", + "integrity": "sha512-RbJ5/jmFcNNCcDV5o9eTnBLJ/HszWV0P73bc+Ff4nS/rJj+YaS6IGyiOL0VoBYX+l1Wrl3k63h/KrH+nhJ0XvQ==", + "dev": true, + "license": "ISC" + }, + "node_modules/handlebars": { + "version": "4.7.8", + "resolved": "https://registry.npmjs.org/handlebars/-/handlebars-4.7.8.tgz", + "integrity": "sha512-vafaFqs8MZkRrSX7sFVUdo3ap/eNiLnb4IakshzvP56X5Nr1iGKAIqdX6tMlm6HcNRIkr6AxO5jFEoJzzpT8aQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "minimist": "^1.2.5", + "neo-async": "^2.6.2", + "source-map": "^0.6.1", + "wordwrap": "^1.0.0" + }, + "bin": { + "handlebars": "bin/handlebars" + }, + "engines": { + "node": ">=0.4.7" + }, + "optionalDependencies": { + "uglify-js": "^3.1.4" + } + }, + "node_modules/has-flag": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", + "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=8" + } + }, + "node_modules/has-symbols": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/has-symbols/-/has-symbols-1.1.0.tgz", + "integrity": "sha512-1cDNdwJ2Jaohmb3sg4OmKaMBwuC48sYni5HUw2DvsC8LjGTLK9h+eb1X6RyuOHe4hT0ULCW68iomhjUoKUqlPQ==", + "license": "MIT", + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/hasown": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/hasown/-/hasown-2.0.2.tgz", + "integrity": "sha512-0hJU9SCPvmMzIBdZFqNPXWa6dqh7WdH0cII9y+CyS8rG3nL48Bclra9HmKhVVUHyPWNH5Y7xDwAB7bfgSjkUMQ==", + "license": "MIT", + "dependencies": { + "function-bind": "^1.1.2" + }, + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/html-escaper": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/html-escaper/-/html-escaper-2.0.2.tgz", + "integrity": "sha512-H2iMtd0I4Mt5eYiapRdIDjp+XzelXQ0tFE4JS7YFwFevXXMmOp9myNrUvCg0D6ws8iqkRPBfKHgbwig1SmlLfg==", + "dev": true, + "license": "MIT" + }, + "node_modules/http-errors": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/http-errors/-/http-errors-2.0.1.tgz", + "integrity": "sha512-4FbRdAX+bSdmo4AUFuS0WNiPz8NgFt+r8ThgNWmlrjQjt1Q7ZR9+zTlce2859x4KSXrwIsaeTqDoKQmtP8pLmQ==", + "license": "MIT", + "dependencies": { + "depd": "~2.0.0", + "inherits": "~2.0.4", + "setprototypeof": "~1.2.0", + "statuses": "~2.0.2", + "toidentifier": "~1.0.1" + }, + "engines": { + "node": ">= 0.8" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/express" + } + }, + "node_modules/human-signals": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/human-signals/-/human-signals-2.1.0.tgz", + "integrity": "sha512-B4FFZ6q/T2jhhksgkbEW3HBvWIfDW85snkQgawt07S7J5QXTk6BkNV+0yAeZrM5QpMAdYlocGoljn0sJ/WQkFw==", + "dev": true, + "license": "Apache-2.0", + "engines": { + "node": ">=10.17.0" + } + }, + "node_modules/iconv-lite": { + "version": "0.4.24", + "resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.4.24.tgz", + "integrity": "sha512-v3MXnZAcvnywkTUEZomIActle7RXXeedOR31wwl7VlyoXO4Qi9arvSenNQWne1TcRwhCL1HwLI21bEqdpj8/rA==", + "license": "MIT", + "dependencies": { + "safer-buffer": ">= 2.1.2 < 3" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/ignore-by-default": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/ignore-by-default/-/ignore-by-default-1.0.1.tgz", + "integrity": "sha512-Ius2VYcGNk7T90CppJqcIkS5ooHUZyIQK+ClZfMfMNFEF9VSE73Fq+906u/CWu92x4gzZMWOwfFYckPObzdEbA==", + "dev": true, + "license": "ISC" + }, + "node_modules/import-local": { + "version": "3.2.0", + "resolved": "https://registry.npmjs.org/import-local/-/import-local-3.2.0.tgz", + "integrity": "sha512-2SPlun1JUPWoM6t3F0dw0FkCF/jWY8kttcY4f599GLTSjh2OCuuhdTkJQsEcZzBqbXZGKMK2OqW1oZsjtf/gQA==", + "dev": true, + "license": "MIT", + "dependencies": { + "pkg-dir": "^4.2.0", + "resolve-cwd": "^3.0.0" + }, + "bin": { + "import-local-fixture": "fixtures/cli.js" + }, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/imurmurhash": { + "version": "0.1.4", + "resolved": "https://registry.npmjs.org/imurmurhash/-/imurmurhash-0.1.4.tgz", + "integrity": "sha512-JmXMZ6wuvDmLiHEml9ykzqO6lwFbof0GG4IkcGaENdCRDDmMVnny7s5HsIgHCbaq0w2MyPhDqkhTUgS2LU2PHA==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=0.8.19" + } + }, + "node_modules/inflight": { + "version": "1.0.6", + "resolved": "https://registry.npmjs.org/inflight/-/inflight-1.0.6.tgz", + "integrity": "sha512-k92I/b08q4wvFscXCLvqfsHCrjrF7yiXsQuIVvVE7N82W3+aqpzuUdBbfhWcy/FZR3/4IgflMgKLOsvPDrGCJA==", + "deprecated": "This module is not supported, and leaks memory. Do not use it. Check out lru-cache if you want a good and tested way to coalesce async requests by a key value, which is much more comprehensive and powerful.", + "dev": true, + "license": "ISC", + "dependencies": { + "once": "^1.3.0", + "wrappy": "1" + } + }, + "node_modules/inherits": { + "version": "2.0.4", + "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.4.tgz", + "integrity": "sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==", + "license": "ISC" + }, + "node_modules/ipaddr.js": { + "version": "1.9.1", + "resolved": "https://registry.npmjs.org/ipaddr.js/-/ipaddr.js-1.9.1.tgz", + "integrity": "sha512-0KI/607xoxSToH7GjN1FfSbLoU0+btTicjsQSWQlh/hZykN8KpmMf7uYwPW3R+akZ6R/w18ZlXSHBYXiYUPO3g==", + "license": "MIT", + "engines": { + "node": ">= 0.10" + } + }, + "node_modules/is-arrayish": { + "version": "0.2.1", + "resolved": "https://registry.npmjs.org/is-arrayish/-/is-arrayish-0.2.1.tgz", + "integrity": "sha512-zz06S8t0ozoDXMG+ube26zeCTNXcKIPJZJi8hBrF4idCLms4CG9QtK7qBl1boi5ODzFpjswb5JPmHCbMpjaYzg==", + "dev": true, + "license": "MIT" + }, + "node_modules/is-binary-path": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/is-binary-path/-/is-binary-path-2.1.0.tgz", + "integrity": "sha512-ZMERYes6pDydyuGidse7OsHxtbI7WVeUEozgR/g7rd0xUimYNlvZRE/K2MgZTjWy725IfelLeVcEM97mmtRGXw==", + "dev": true, + "license": "MIT", + "dependencies": { + "binary-extensions": "^2.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/is-core-module": { + "version": "2.16.1", + "resolved": "https://registry.npmjs.org/is-core-module/-/is-core-module-2.16.1.tgz", + "integrity": "sha512-UfoeMA6fIJ8wTYFEUjelnaGI67v6+N7qXJEvQuIGa99l4xsCruSYOVSQ0uPANn4dAzm8lkYPaKLrrijLq7x23w==", + "dev": true, + "license": "MIT", + "dependencies": { + "hasown": "^2.0.2" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/is-extglob": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/is-extglob/-/is-extglob-2.1.1.tgz", + "integrity": "sha512-SbKbANkN603Vi4jEZv49LeVJMn4yGwsbzZworEoyEiutsN3nJYdbO36zfhGJ6QEDpOZIFkDtnq5JRxmvl3jsoQ==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/is-fullwidth-code-point": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-3.0.0.tgz", + "integrity": "sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=8" + } + }, + "node_modules/is-generator-fn": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/is-generator-fn/-/is-generator-fn-2.1.0.tgz", + "integrity": "sha512-cTIB4yPYL/Grw0EaSzASzg6bBy9gqCofvWN8okThAYIxKJZC+udlRAmGbM0XLeniEJSs8uEgHPGuHSe1XsOLSQ==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=6" + } + }, + "node_modules/is-glob": { + "version": "4.0.3", + "resolved": "https://registry.npmjs.org/is-glob/-/is-glob-4.0.3.tgz", + "integrity": "sha512-xelSayHH36ZgE7ZWhli7pW34hNbNl8Ojv5KVmkJD4hBdD3th8Tfk9vYasLM+mXWOZhFkgZfxhLSnrwRr4elSSg==", + "dev": true, + "license": "MIT", + "dependencies": { + "is-extglob": "^2.1.1" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/is-number": { + "version": "7.0.0", + "resolved": "https://registry.npmjs.org/is-number/-/is-number-7.0.0.tgz", + "integrity": "sha512-41Cifkg6e8TylSpdtTpeLVMqvSBEVzTttHvERD741+pnZ8ANv0004MRL43QKPDlK9cGvNp6NZWZUBlbGXYxxng==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=0.12.0" + } + }, + "node_modules/is-stream": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/is-stream/-/is-stream-2.0.1.tgz", + "integrity": "sha512-hFoiJiTl63nn+kstHGBtewWSKnQLpyb155KHheA1l39uvtO9nWIop1p3udqPcUd/xbF1VLMO4n7OI6p7RbngDg==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/isexe": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/isexe/-/isexe-2.0.0.tgz", + "integrity": "sha512-RHxMLp9lnKHGHRng9QFhRCMbYAcVpn69smSGcq3f36xjgVVWThj4qqLbTLlq7Ssj8B+fIQ1EuCEGI2lKsyQeIw==", + "dev": true, + "license": "ISC" + }, + "node_modules/istanbul-lib-coverage": { + "version": "3.2.2", + "resolved": "https://registry.npmjs.org/istanbul-lib-coverage/-/istanbul-lib-coverage-3.2.2.tgz", + "integrity": "sha512-O8dpsF+r0WV/8MNRKfnmrtCWhuKjxrq2w+jpzBL5UZKTi2LeVWnWOmWRxFlesJONmc+wLAGvKQZEOanko0LFTg==", + "dev": true, + "license": "BSD-3-Clause", + "engines": { + "node": ">=8" + } + }, + "node_modules/istanbul-lib-instrument": { + "version": "6.0.3", + "resolved": "https://registry.npmjs.org/istanbul-lib-instrument/-/istanbul-lib-instrument-6.0.3.tgz", + "integrity": "sha512-Vtgk7L/R2JHyyGW07spoFlB8/lpjiOLTjMdms6AFMraYt3BaJauod/NGrfnVG/y4Ix1JEuMRPDPEj2ua+zz1/Q==", + "dev": true, + "license": "BSD-3-Clause", + "dependencies": { + "@babel/core": "^7.23.9", + "@babel/parser": "^7.23.9", + "@istanbuljs/schema": "^0.1.3", + "istanbul-lib-coverage": "^3.2.0", + "semver": "^7.5.4" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/istanbul-lib-instrument/node_modules/semver": { + "version": "7.7.4", + "resolved": "https://registry.npmjs.org/semver/-/semver-7.7.4.tgz", + "integrity": "sha512-vFKC2IEtQnVhpT78h1Yp8wzwrf8CM+MzKMHGJZfBtzhZNycRFnXsHk6E5TxIkkMsgNS7mdX3AGB7x2QM2di4lA==", + "dev": true, + "license": "ISC", + "bin": { + "semver": "bin/semver.js" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/istanbul-lib-report": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/istanbul-lib-report/-/istanbul-lib-report-3.0.1.tgz", + "integrity": "sha512-GCfE1mtsHGOELCU8e/Z7YWzpmybrx/+dSTfLrvY8qRmaY6zXTKWn6WQIjaAFw069icm6GVMNkgu0NzI4iPZUNw==", + "dev": true, + "license": "BSD-3-Clause", + "dependencies": { + "istanbul-lib-coverage": "^3.0.0", + "make-dir": "^4.0.0", + "supports-color": "^7.1.0" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/istanbul-lib-source-maps": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/istanbul-lib-source-maps/-/istanbul-lib-source-maps-4.0.1.tgz", + "integrity": "sha512-n3s8EwkdFIJCG3BPKBYvskgXGoy88ARzvegkitk60NxRdwltLOTaH7CUiMRXvwYorl0Q712iEjcWB+fK/MrWVw==", + "dev": true, + "license": "BSD-3-Clause", + "dependencies": { + "debug": "^4.1.1", + "istanbul-lib-coverage": "^3.0.0", + "source-map": "^0.6.1" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/istanbul-lib-source-maps/node_modules/debug": { + "version": "4.4.3", + "resolved": "https://registry.npmjs.org/debug/-/debug-4.4.3.tgz", + "integrity": "sha512-RGwwWnwQvkVfavKVt22FGLw+xYSdzARwm0ru6DhTVA3umU5hZc28V3kO4stgYryrTlLpuvgI9GiijltAjNbcqA==", + "dev": true, + "license": "MIT", + "dependencies": { + "ms": "^2.1.3" + }, + "engines": { + "node": ">=6.0" + }, + "peerDependenciesMeta": { + "supports-color": { + "optional": true + } + } + }, + "node_modules/istanbul-lib-source-maps/node_modules/ms": { + "version": "2.1.3", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.3.tgz", + "integrity": "sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==", + "dev": true, + "license": "MIT" + }, + "node_modules/istanbul-reports": { + "version": "3.2.0", + "resolved": "https://registry.npmjs.org/istanbul-reports/-/istanbul-reports-3.2.0.tgz", + "integrity": "sha512-HGYWWS/ehqTV3xN10i23tkPkpH46MLCIMFNCaaKNavAXTF1RkqxawEPtnjnGZ6XKSInBKkiOA5BKS+aZiY3AvA==", + "dev": true, + "license": "BSD-3-Clause", + "dependencies": { + "html-escaper": "^2.0.0", + "istanbul-lib-report": "^3.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/jest": { + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/jest/-/jest-29.7.0.tgz", + "integrity": "sha512-NIy3oAFp9shda19hy4HK0HRTWKtPJmGdnvywu01nOqNC2vZg+Z+fvJDxpMQA88eb2I9EcafcdjYgsDthnYTvGw==", + "dev": true, + "license": "MIT", + "peer": true, + "dependencies": { + "@jest/core": "^29.7.0", + "@jest/types": "^29.6.3", + "import-local": "^3.0.2", + "jest-cli": "^29.7.0" + }, + "bin": { + "jest": "bin/jest.js" + }, + "engines": { + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + }, + "peerDependencies": { + "node-notifier": "^8.0.1 || ^9.0.0 || ^10.0.0" + }, + "peerDependenciesMeta": { + "node-notifier": { + "optional": true + } + } + }, + "node_modules/jest-changed-files": { + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/jest-changed-files/-/jest-changed-files-29.7.0.tgz", + "integrity": "sha512-fEArFiwf1BpQ+4bXSprcDc3/x4HSzL4al2tozwVpDFpsxALjLYdyiIK4e5Vz66GQJIbXJ82+35PtysofptNX2w==", + "dev": true, + "license": "MIT", + "dependencies": { + "execa": "^5.0.0", + "jest-util": "^29.7.0", + "p-limit": "^3.1.0" + }, + "engines": { + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + } + }, + "node_modules/jest-circus": { + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/jest-circus/-/jest-circus-29.7.0.tgz", + "integrity": "sha512-3E1nCMgipcTkCocFwM90XXQab9bS+GMsjdpmPrlelaxwD93Ad8iVEjX/vvHPdLPnFf+L40u+5+iutRdA1N9myw==", + "dev": true, + "license": "MIT", + "dependencies": { + "@jest/environment": "^29.7.0", + "@jest/expect": "^29.7.0", + "@jest/test-result": "^29.7.0", + "@jest/types": "^29.6.3", + "@types/node": "*", + "chalk": "^4.0.0", + "co": "^4.6.0", + "dedent": "^1.0.0", + "is-generator-fn": "^2.0.0", + "jest-each": "^29.7.0", + "jest-matcher-utils": "^29.7.0", + "jest-message-util": "^29.7.0", + "jest-runtime": "^29.7.0", + "jest-snapshot": "^29.7.0", + "jest-util": "^29.7.0", + "p-limit": "^3.1.0", + "pretty-format": "^29.7.0", + "pure-rand": "^6.0.0", + "slash": "^3.0.0", + "stack-utils": "^2.0.3" + }, + "engines": { + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + } + }, + "node_modules/jest-cli": { + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/jest-cli/-/jest-cli-29.7.0.tgz", + "integrity": "sha512-OVVobw2IubN/GSYsxETi+gOe7Ka59EFMR/twOU3Jb2GnKKeMGJB5SGUUrEz3SFVmJASUdZUzy83sLNNQ2gZslg==", + "dev": true, + "license": "MIT", + "dependencies": { + "@jest/core": "^29.7.0", + "@jest/test-result": "^29.7.0", + "@jest/types": "^29.6.3", + "chalk": "^4.0.0", + "create-jest": "^29.7.0", + "exit": "^0.1.2", + "import-local": "^3.0.2", + "jest-config": "^29.7.0", + "jest-util": "^29.7.0", + "jest-validate": "^29.7.0", + "yargs": "^17.3.1" + }, + "bin": { + "jest": "bin/jest.js" + }, + "engines": { + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + }, + "peerDependencies": { + "node-notifier": "^8.0.1 || ^9.0.0 || ^10.0.0" + }, + "peerDependenciesMeta": { + "node-notifier": { + "optional": true + } + } + }, + "node_modules/jest-config": { + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/jest-config/-/jest-config-29.7.0.tgz", + "integrity": "sha512-uXbpfeQ7R6TZBqI3/TxCU4q4ttk3u0PJeC+E0zbfSoSjq6bJ7buBPxzQPL0ifrkY4DNu4JUdk0ImlBUYi840eQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/core": "^7.11.6", + "@jest/test-sequencer": "^29.7.0", + "@jest/types": "^29.6.3", + "babel-jest": "^29.7.0", + "chalk": "^4.0.0", + "ci-info": "^3.2.0", + "deepmerge": "^4.2.2", + "glob": "^7.1.3", + "graceful-fs": "^4.2.9", + "jest-circus": "^29.7.0", + "jest-environment-node": "^29.7.0", + "jest-get-type": "^29.6.3", + "jest-regex-util": "^29.6.3", + "jest-resolve": "^29.7.0", + "jest-runner": "^29.7.0", + "jest-util": "^29.7.0", + "jest-validate": "^29.7.0", + "micromatch": "^4.0.4", + "parse-json": "^5.2.0", + "pretty-format": "^29.7.0", + "slash": "^3.0.0", + "strip-json-comments": "^3.1.1" + }, + "engines": { + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + }, + "peerDependencies": { + "@types/node": "*", + "ts-node": ">=9.0.0" + }, + "peerDependenciesMeta": { + "@types/node": { + "optional": true + }, + "ts-node": { + "optional": true + } + } + }, + "node_modules/jest-diff": { + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/jest-diff/-/jest-diff-29.7.0.tgz", + "integrity": "sha512-LMIgiIrhigmPrs03JHpxUh2yISK3vLFPkAodPeo0+BuF7wA2FoQbkEg1u8gBYBThncu7e1oEDUfIXVuTqLRUjw==", + "dev": true, + "license": "MIT", + "dependencies": { + "chalk": "^4.0.0", + "diff-sequences": "^29.6.3", + "jest-get-type": "^29.6.3", + "pretty-format": "^29.7.0" + }, + "engines": { + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + } + }, + "node_modules/jest-docblock": { + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/jest-docblock/-/jest-docblock-29.7.0.tgz", + "integrity": "sha512-q617Auw3A612guyaFgsbFeYpNP5t2aoUNLwBUbc/0kD1R4t9ixDbyFTHd1nok4epoVFpr7PmeWHrhvuV3XaJ4g==", + "dev": true, + "license": "MIT", + "dependencies": { + "detect-newline": "^3.0.0" + }, + "engines": { + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + } + }, + "node_modules/jest-each": { + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/jest-each/-/jest-each-29.7.0.tgz", + "integrity": "sha512-gns+Er14+ZrEoC5fhOfYCY1LOHHr0TI+rQUHZS8Ttw2l7gl+80eHc/gFf2Ktkw0+SIACDTeWvpFcv3B04VembQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "@jest/types": "^29.6.3", + "chalk": "^4.0.0", + "jest-get-type": "^29.6.3", + "jest-util": "^29.7.0", + "pretty-format": "^29.7.0" + }, + "engines": { + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + } + }, + "node_modules/jest-environment-node": { + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/jest-environment-node/-/jest-environment-node-29.7.0.tgz", + "integrity": "sha512-DOSwCRqXirTOyheM+4d5YZOrWcdu0LNZ87ewUoywbcb2XR4wKgqiG8vNeYwhjFMbEkfju7wx2GYH0P2gevGvFw==", + "dev": true, + "license": "MIT", + "dependencies": { + "@jest/environment": "^29.7.0", + "@jest/fake-timers": "^29.7.0", + "@jest/types": "^29.6.3", + "@types/node": "*", + "jest-mock": "^29.7.0", + "jest-util": "^29.7.0" + }, + "engines": { + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + } + }, + "node_modules/jest-get-type": { + "version": "29.6.3", + "resolved": "https://registry.npmjs.org/jest-get-type/-/jest-get-type-29.6.3.tgz", + "integrity": "sha512-zrteXnqYxfQh7l5FHyL38jL39di8H8rHoecLH3JNxH3BwOrBsNeabdap5e0I23lD4HHI8W5VFBZqG4Eaq5LNcw==", + "dev": true, + "license": "MIT", + "engines": { + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + } + }, + "node_modules/jest-haste-map": { + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/jest-haste-map/-/jest-haste-map-29.7.0.tgz", + "integrity": "sha512-fP8u2pyfqx0K1rGn1R9pyE0/KTn+G7PxktWidOBTqFPLYX0b9ksaMFkhK5vrS3DVun09pckLdlx90QthlW7AmA==", + "dev": true, + "license": "MIT", + "dependencies": { + "@jest/types": "^29.6.3", + "@types/graceful-fs": "^4.1.3", + "@types/node": "*", + "anymatch": "^3.0.3", + "fb-watchman": "^2.0.0", + "graceful-fs": "^4.2.9", + "jest-regex-util": "^29.6.3", + "jest-util": "^29.7.0", + "jest-worker": "^29.7.0", + "micromatch": "^4.0.4", + "walker": "^1.0.8" + }, + "engines": { + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + }, + "optionalDependencies": { + "fsevents": "^2.3.2" + } + }, + "node_modules/jest-leak-detector": { + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/jest-leak-detector/-/jest-leak-detector-29.7.0.tgz", + "integrity": "sha512-kYA8IJcSYtST2BY9I+SMC32nDpBT3J2NvWJx8+JCuCdl/CR1I4EKUJROiP8XtCcxqgTTBGJNdbB1A8XRKbTetw==", + "dev": true, + "license": "MIT", + "dependencies": { + "jest-get-type": "^29.6.3", + "pretty-format": "^29.7.0" + }, + "engines": { + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + } + }, + "node_modules/jest-matcher-utils": { + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/jest-matcher-utils/-/jest-matcher-utils-29.7.0.tgz", + "integrity": "sha512-sBkD+Xi9DtcChsI3L3u0+N0opgPYnCRPtGcQYrgXmR+hmt/fYfWAL0xRXYU8eWOdfuLgBe0YCW3AFtnRLagq/g==", + "dev": true, + "license": "MIT", + "dependencies": { + "chalk": "^4.0.0", + "jest-diff": "^29.7.0", + "jest-get-type": "^29.6.3", + "pretty-format": "^29.7.0" + }, + "engines": { + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + } + }, + "node_modules/jest-message-util": { + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/jest-message-util/-/jest-message-util-29.7.0.tgz", + "integrity": "sha512-GBEV4GRADeP+qtB2+6u61stea8mGcOT4mCtrYISZwfu9/ISHFJ/5zOMXYbpBE9RsS5+Gb63DW4FgmnKJ79Kf6w==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/code-frame": "^7.12.13", + "@jest/types": "^29.6.3", + "@types/stack-utils": "^2.0.0", + "chalk": "^4.0.0", + "graceful-fs": "^4.2.9", + "micromatch": "^4.0.4", + "pretty-format": "^29.7.0", + "slash": "^3.0.0", + "stack-utils": "^2.0.3" + }, + "engines": { + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + } + }, + "node_modules/jest-mock": { + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/jest-mock/-/jest-mock-29.7.0.tgz", + "integrity": "sha512-ITOMZn+UkYS4ZFh83xYAOzWStloNzJFO2s8DWrE4lhtGD+AorgnbkiKERe4wQVBydIGPx059g6riW5Btp6Llnw==", + "dev": true, + "license": "MIT", + "dependencies": { + "@jest/types": "^29.6.3", + "@types/node": "*", + "jest-util": "^29.7.0" + }, + "engines": { + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + } + }, + "node_modules/jest-pnp-resolver": { + "version": "1.2.3", + "resolved": "https://registry.npmjs.org/jest-pnp-resolver/-/jest-pnp-resolver-1.2.3.tgz", + "integrity": "sha512-+3NpwQEnRoIBtx4fyhblQDPgJI0H1IEIkX7ShLUjPGA7TtUTvI1oiKi3SR4oBR0hQhQR80l4WAe5RrXBwWMA8w==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=6" + }, + "peerDependencies": { + "jest-resolve": "*" + }, + "peerDependenciesMeta": { + "jest-resolve": { + "optional": true + } + } + }, + "node_modules/jest-regex-util": { + "version": "29.6.3", + "resolved": "https://registry.npmjs.org/jest-regex-util/-/jest-regex-util-29.6.3.tgz", + "integrity": "sha512-KJJBsRCyyLNWCNBOvZyRDnAIfUiRJ8v+hOBQYGn8gDyF3UegwiP4gwRR3/SDa42g1YbVycTidUF3rKjyLFDWbg==", + "dev": true, + "license": "MIT", + "engines": { + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + } + }, + "node_modules/jest-resolve": { + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/jest-resolve/-/jest-resolve-29.7.0.tgz", + "integrity": "sha512-IOVhZSrg+UvVAshDSDtHyFCCBUl/Q3AAJv8iZ6ZjnZ74xzvwuzLXid9IIIPgTnY62SJjfuupMKZsZQRsCvxEgA==", + "dev": true, + "license": "MIT", + "dependencies": { + "chalk": "^4.0.0", + "graceful-fs": "^4.2.9", + "jest-haste-map": "^29.7.0", + "jest-pnp-resolver": "^1.2.2", + "jest-util": "^29.7.0", + "jest-validate": "^29.7.0", + "resolve": "^1.20.0", + "resolve.exports": "^2.0.0", + "slash": "^3.0.0" + }, + "engines": { + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + } + }, + "node_modules/jest-resolve-dependencies": { + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/jest-resolve-dependencies/-/jest-resolve-dependencies-29.7.0.tgz", + "integrity": "sha512-un0zD/6qxJ+S0et7WxeI3H5XSe9lTBBR7bOHCHXkKR6luG5mwDDlIzVQ0V5cZCuoTgEdcdwzTghYkTWfubi+nA==", + "dev": true, + "license": "MIT", + "dependencies": { + "jest-regex-util": "^29.6.3", + "jest-snapshot": "^29.7.0" + }, + "engines": { + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + } + }, + "node_modules/jest-runner": { + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/jest-runner/-/jest-runner-29.7.0.tgz", + "integrity": "sha512-fsc4N6cPCAahybGBfTRcq5wFR6fpLznMg47sY5aDpsoejOcVYFb07AHuSnR0liMcPTgBsA3ZJL6kFOjPdoNipQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "@jest/console": "^29.7.0", + "@jest/environment": "^29.7.0", + "@jest/test-result": "^29.7.0", + "@jest/transform": "^29.7.0", + "@jest/types": "^29.6.3", + "@types/node": "*", + "chalk": "^4.0.0", + "emittery": "^0.13.1", + "graceful-fs": "^4.2.9", + "jest-docblock": "^29.7.0", + "jest-environment-node": "^29.7.0", + "jest-haste-map": "^29.7.0", + "jest-leak-detector": "^29.7.0", + "jest-message-util": "^29.7.0", + "jest-resolve": "^29.7.0", + "jest-runtime": "^29.7.0", + "jest-util": "^29.7.0", + "jest-watcher": "^29.7.0", + "jest-worker": "^29.7.0", + "p-limit": "^3.1.0", + "source-map-support": "0.5.13" + }, + "engines": { + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + } + }, + "node_modules/jest-runtime": { + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/jest-runtime/-/jest-runtime-29.7.0.tgz", + "integrity": "sha512-gUnLjgwdGqW7B4LvOIkbKs9WGbn+QLqRQQ9juC6HndeDiezIwhDP+mhMwHWCEcfQ5RUXa6OPnFF8BJh5xegwwQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "@jest/environment": "^29.7.0", + "@jest/fake-timers": "^29.7.0", + "@jest/globals": "^29.7.0", + "@jest/source-map": "^29.6.3", + "@jest/test-result": "^29.7.0", + "@jest/transform": "^29.7.0", + "@jest/types": "^29.6.3", + "@types/node": "*", + "chalk": "^4.0.0", + "cjs-module-lexer": "^1.0.0", + "collect-v8-coverage": "^1.0.0", + "glob": "^7.1.3", + "graceful-fs": "^4.2.9", + "jest-haste-map": "^29.7.0", + "jest-message-util": "^29.7.0", + "jest-mock": "^29.7.0", + "jest-regex-util": "^29.6.3", + "jest-resolve": "^29.7.0", + "jest-snapshot": "^29.7.0", + "jest-util": "^29.7.0", + "slash": "^3.0.0", + "strip-bom": "^4.0.0" + }, + "engines": { + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + } + }, + "node_modules/jest-snapshot": { + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/jest-snapshot/-/jest-snapshot-29.7.0.tgz", + "integrity": "sha512-Rm0BMWtxBcioHr1/OX5YCP8Uov4riHvKPknOGs804Zg9JGZgmIBkbtlxJC/7Z4msKYVbIJtfU+tKb8xlYNfdkw==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/core": "^7.11.6", + "@babel/generator": "^7.7.2", + "@babel/plugin-syntax-jsx": "^7.7.2", + "@babel/plugin-syntax-typescript": "^7.7.2", + "@babel/types": "^7.3.3", + "@jest/expect-utils": "^29.7.0", + "@jest/transform": "^29.7.0", + "@jest/types": "^29.6.3", + "babel-preset-current-node-syntax": "^1.0.0", + "chalk": "^4.0.0", + "expect": "^29.7.0", + "graceful-fs": "^4.2.9", + "jest-diff": "^29.7.0", + "jest-get-type": "^29.6.3", + "jest-matcher-utils": "^29.7.0", + "jest-message-util": "^29.7.0", + "jest-util": "^29.7.0", + "natural-compare": "^1.4.0", + "pretty-format": "^29.7.0", + "semver": "^7.5.3" + }, + "engines": { + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + } + }, + "node_modules/jest-snapshot/node_modules/semver": { + "version": "7.7.4", + "resolved": "https://registry.npmjs.org/semver/-/semver-7.7.4.tgz", + "integrity": "sha512-vFKC2IEtQnVhpT78h1Yp8wzwrf8CM+MzKMHGJZfBtzhZNycRFnXsHk6E5TxIkkMsgNS7mdX3AGB7x2QM2di4lA==", + "dev": true, + "license": "ISC", + "bin": { + "semver": "bin/semver.js" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/jest-util": { + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/jest-util/-/jest-util-29.7.0.tgz", + "integrity": "sha512-z6EbKajIpqGKU56y5KBUgy1dt1ihhQJgWzUlZHArA/+X2ad7Cb5iF+AK1EWVL/Bo7Rz9uurpqw6SiBCefUbCGA==", + "dev": true, + "license": "MIT", + "dependencies": { + "@jest/types": "^29.6.3", + "@types/node": "*", + "chalk": "^4.0.0", + "ci-info": "^3.2.0", + "graceful-fs": "^4.2.9", + "picomatch": "^2.2.3" + }, + "engines": { + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + } + }, + "node_modules/jest-validate": { + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/jest-validate/-/jest-validate-29.7.0.tgz", + "integrity": "sha512-ZB7wHqaRGVw/9hST/OuFUReG7M8vKeq0/J2egIGLdvjHCmYqGARhzXmtgi+gVeZ5uXFF219aOc3Ls2yLg27tkw==", + "dev": true, + "license": "MIT", + "dependencies": { + "@jest/types": "^29.6.3", + "camelcase": "^6.2.0", + "chalk": "^4.0.0", + "jest-get-type": "^29.6.3", + "leven": "^3.1.0", + "pretty-format": "^29.7.0" + }, + "engines": { + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + } + }, + "node_modules/jest-validate/node_modules/camelcase": { + "version": "6.3.0", + "resolved": "https://registry.npmjs.org/camelcase/-/camelcase-6.3.0.tgz", + "integrity": "sha512-Gmy6FhYlCY7uOElZUSbxo2UCDH8owEk996gkbrpsgGtrJLM3J7jGxl9Ic7Qwwj4ivOE5AWZWRMecDdF7hqGjFA==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/jest-watcher": { + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/jest-watcher/-/jest-watcher-29.7.0.tgz", + "integrity": "sha512-49Fg7WXkU3Vl2h6LbLtMQ/HyB6rXSIX7SqvBLQmssRBGN9I0PNvPmAmCWSOY6SOvrjhI/F7/bGAv9RtnsPA03g==", + "dev": true, + "license": "MIT", + "dependencies": { + "@jest/test-result": "^29.7.0", + "@jest/types": "^29.6.3", + "@types/node": "*", + "ansi-escapes": "^4.2.1", + "chalk": "^4.0.0", + "emittery": "^0.13.1", + "jest-util": "^29.7.0", + "string-length": "^4.0.1" + }, + "engines": { + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + } + }, + "node_modules/jest-worker": { + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/jest-worker/-/jest-worker-29.7.0.tgz", + "integrity": "sha512-eIz2msL/EzL9UFTFFx7jBTkeZfku0yUAyZZZmJ93H2TYEiroIx2PQjEXcwYtYl8zXCxb+PAmA2hLIt/6ZEkPHw==", + "dev": true, + "license": "MIT", + "dependencies": { + "@types/node": "*", + "jest-util": "^29.7.0", + "merge-stream": "^2.0.0", + "supports-color": "^8.0.0" + }, + "engines": { + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + } + }, + "node_modules/jest-worker/node_modules/supports-color": { + "version": "8.1.1", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-8.1.1.tgz", + "integrity": "sha512-MpUEN2OodtUzxvKQl72cUF7RQ5EiHsGvSsVG0ia9c5RbWGL2CI4C7EpPS8UTBIplnlzZiNuV56w+FuNxy3ty2Q==", + "dev": true, + "license": "MIT", + "dependencies": { + "has-flag": "^4.0.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/chalk/supports-color?sponsor=1" + } + }, + "node_modules/js-tokens": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/js-tokens/-/js-tokens-4.0.0.tgz", + "integrity": "sha512-RdJUflcE3cUzKiMqQgsCu06FPu9UdIJO0beYbPhHN4k6apgJtifcoCtT9bcxOpYBtpD2kCM6Sbzg4CausW/PKQ==", + "dev": true, + "license": "MIT" + }, + "node_modules/js-yaml": { + "version": "3.14.2", + "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-3.14.2.tgz", + "integrity": "sha512-PMSmkqxr106Xa156c2M265Z+FTrPl+oxd/rgOQy2tijQeK5TxQ43psO1ZCwhVOSdnn+RzkzlRz/eY4BgJBYVpg==", + "dev": true, + "license": "MIT", + "dependencies": { + "argparse": "^1.0.7", + "esprima": "^4.0.0" + }, + "bin": { + "js-yaml": "bin/js-yaml.js" + } + }, + "node_modules/jsesc": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/jsesc/-/jsesc-3.1.0.tgz", + "integrity": "sha512-/sM3dO2FOzXjKQhJuo0Q173wf2KOo8t4I8vHy6lF9poUp7bKT0/NHE8fPX23PwfhnykfqnC2xRxOnVw5XuGIaA==", + "dev": true, + "license": "MIT", + "bin": { + "jsesc": "bin/jsesc" + }, + "engines": { + "node": ">=6" + } + }, + "node_modules/json-parse-even-better-errors": { + "version": "2.3.1", + "resolved": "https://registry.npmjs.org/json-parse-even-better-errors/-/json-parse-even-better-errors-2.3.1.tgz", + "integrity": "sha512-xyFwyhro/JEof6Ghe2iz2NcXoj2sloNsWr/XsERDK/oiPCfaNhl5ONfp+jQdAZRQQ0IJWNzH9zIZF7li91kh2w==", + "dev": true, + "license": "MIT" + }, + "node_modules/json-schema-to-ts": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/json-schema-to-ts/-/json-schema-to-ts-3.1.1.tgz", + "integrity": "sha512-+DWg8jCJG2TEnpy7kOm/7/AxaYoaRbjVB4LFZLySZlWn8exGs3A4OLJR966cVvU26N7X9TWxl+Jsw7dzAqKT6g==", + "license": "MIT", + "dependencies": { + "@babel/runtime": "^7.18.3", + "ts-algebra": "^2.0.0" + }, + "engines": { + "node": ">=16" + } + }, + "node_modules/json5": { + "version": "2.2.3", + "resolved": "https://registry.npmjs.org/json5/-/json5-2.2.3.tgz", + "integrity": "sha512-XmOWe7eyHYH14cLdVPoyg+GOH3rYX++KpzrylJwSW98t3Nk+U8XOl8FWKOgwtzdb8lXGf6zYwDUzeHMWfxasyg==", + "dev": true, + "license": "MIT", + "bin": { + "json5": "lib/cli.js" + }, + "engines": { + "node": ">=6" + } + }, + "node_modules/kleur": { + "version": "3.0.3", + "resolved": "https://registry.npmjs.org/kleur/-/kleur-3.0.3.tgz", + "integrity": "sha512-eTIzlVOSUR+JxdDFepEYcBMtZ9Qqdef+rnzWdRZuMbOywu5tO2w2N7rqjoANZ5k9vywhL6Br1VRjUIgTQx4E8w==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=6" + } + }, + "node_modules/leven": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/leven/-/leven-3.1.0.tgz", + "integrity": "sha512-qsda+H8jTaUaN/x5vzW2rzc+8Rw4TAQ/4KjB46IwK5VH+IlVeeeje/EoZRpiXvIqjFgK84QffqPztGI3VBLG1A==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=6" + } + }, + "node_modules/lines-and-columns": { + "version": "1.2.4", + "resolved": "https://registry.npmjs.org/lines-and-columns/-/lines-and-columns-1.2.4.tgz", + "integrity": "sha512-7ylylesZQ/PV29jhEDl3Ufjo6ZX7gCqJr5F7PKrqc93v7fzSymt1BpwEU8nAUXs8qzzvqhbjhK5QZg6Mt/HkBg==", + "dev": true, + "license": "MIT" + }, + "node_modules/locate-path": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-5.0.0.tgz", + "integrity": "sha512-t7hw9pI+WvuwNJXwk5zVHpyhIqzg2qTlklJOf0mVxGSbe3Fp2VieZcduNYjaLDoy6p9uGpQEGWG87WpMKlNq8g==", + "dev": true, + "license": "MIT", + "dependencies": { + "p-locate": "^4.1.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/lodash.memoize": { + "version": "4.1.2", + "resolved": "https://registry.npmjs.org/lodash.memoize/-/lodash.memoize-4.1.2.tgz", + "integrity": "sha512-t7j+NzmgnQzTAYXcsHYLgimltOV1MXHtlOWf6GjL9Kj8GK5FInw5JotxvbOs+IvV1/Dzo04/fCGfLVs7aXb4Ag==", + "dev": true, + "license": "MIT" + }, + "node_modules/lru-cache": { + "version": "5.1.1", + "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-5.1.1.tgz", + "integrity": "sha512-KpNARQA3Iwv+jTA0utUVVbrh+Jlrr1Fv0e56GGzAFOXN7dk/FviaDW8LHmK52DlcH4WP2n6gI8vN1aesBFgo9w==", + "dev": true, + "license": "ISC", + "dependencies": { + "yallist": "^3.0.2" + } + }, + "node_modules/make-dir": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/make-dir/-/make-dir-4.0.0.tgz", + "integrity": "sha512-hXdUTZYIVOt1Ex//jAQi+wTZZpUpwBj/0QsOzqegb3rGMMeJiSEu5xLHnYfBrRV4RH2+OCSOO95Is/7x1WJ4bw==", + "dev": true, + "license": "MIT", + "dependencies": { + "semver": "^7.5.3" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/make-dir/node_modules/semver": { + "version": "7.7.4", + "resolved": "https://registry.npmjs.org/semver/-/semver-7.7.4.tgz", + "integrity": "sha512-vFKC2IEtQnVhpT78h1Yp8wzwrf8CM+MzKMHGJZfBtzhZNycRFnXsHk6E5TxIkkMsgNS7mdX3AGB7x2QM2di4lA==", + "dev": true, + "license": "ISC", + "bin": { + "semver": "bin/semver.js" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/make-error": { + "version": "1.3.6", + "resolved": "https://registry.npmjs.org/make-error/-/make-error-1.3.6.tgz", + "integrity": "sha512-s8UhlNe7vPKomQhC1qFelMokr/Sc3AgNbso3n74mVPA5LTZwkB9NlXf4XPamLxJE8h0gh73rM94xvwRT2CVInw==", + "dev": true, + "license": "ISC" + }, + "node_modules/makeerror": { + "version": "1.0.12", + "resolved": "https://registry.npmjs.org/makeerror/-/makeerror-1.0.12.tgz", + "integrity": "sha512-JmqCvUhmt43madlpFzG4BQzG2Z3m6tvQDNKdClZnO3VbIudJYmxsT0FNJMeiB2+JTSlTQTSbU8QdesVmwJcmLg==", + "dev": true, + "license": "BSD-3-Clause", + "dependencies": { + "tmpl": "1.0.5" + } + }, + "node_modules/math-intrinsics": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/math-intrinsics/-/math-intrinsics-1.1.0.tgz", + "integrity": "sha512-/IXtbwEk5HTPyEwyKX6hGkYXxM9nbj64B+ilVJnC/R6B0pH5G4V3b0pVbL7DBj4tkhBAppbQUlf6F6Xl9LHu1g==", + "license": "MIT", + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/media-typer": { + "version": "0.3.0", + "resolved": "https://registry.npmjs.org/media-typer/-/media-typer-0.3.0.tgz", + "integrity": "sha512-dq+qelQ9akHpcOl/gUVRTxVIOkAJ1wR3QAvb4RsVjS8oVoFjDGTc679wJYmUmknUF5HwMLOgb5O+a3KxfWapPQ==", + "license": "MIT", + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/merge-descriptors": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/merge-descriptors/-/merge-descriptors-1.0.3.tgz", + "integrity": "sha512-gaNvAS7TZ897/rVaZ0nMtAyxNyi/pdbjbAwUpFQpN70GqnVfOiXpeUUMKRBmzXaSQ8DdTX4/0ms62r2K+hE6mQ==", + "license": "MIT", + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/merge-stream": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/merge-stream/-/merge-stream-2.0.0.tgz", + "integrity": "sha512-abv/qOcuPfk3URPfDzmZU1LKmuw8kT+0nIHvKrKgFrwifol/doWcdA4ZqsWQ8ENrFKkd67Mfpo/LovbIUsbt3w==", + "dev": true, + "license": "MIT" + }, + "node_modules/methods": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/methods/-/methods-1.1.2.tgz", + "integrity": "sha512-iclAHeNqNm68zFtnZ0e+1L2yUIdvzNoauKU4WBA3VvH/vPFieF7qfRlwUZU+DA9P9bPXIS90ulxoUoCH23sV2w==", + "license": "MIT", + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/micromatch": { + "version": "4.0.8", + "resolved": "https://registry.npmjs.org/micromatch/-/micromatch-4.0.8.tgz", + "integrity": "sha512-PXwfBhYu0hBCPw8Dn0E+WDYb7af3dSLVWKi3HGv84IdF4TyFoC0ysxFd0Goxw7nSv4T/PzEJQxsYsEiFCKo2BA==", + "dev": true, + "license": "MIT", + "dependencies": { + "braces": "^3.0.3", + "picomatch": "^2.3.1" + }, + "engines": { + "node": ">=8.6" + } + }, + "node_modules/mime": { + "version": "1.6.0", + "resolved": "https://registry.npmjs.org/mime/-/mime-1.6.0.tgz", + "integrity": "sha512-x0Vn8spI+wuJ1O6S7gnbaQg8Pxh4NNHb7KSINmEWKiPE4RKOplvijn+NkmYmmRgP68mc70j2EbeTFRsrswaQeg==", + "license": "MIT", + "bin": { + "mime": "cli.js" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/mime-db": { + "version": "1.52.0", + "resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.52.0.tgz", + "integrity": "sha512-sPU4uV7dYlvtWJxwwxHD0PuihVNiE7TyAbQ5SWxDCB9mUYvOgroQOwYQQOKPJ8CIbE+1ETVlOoK1UC2nU3gYvg==", + "license": "MIT", + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/mime-types": { + "version": "2.1.35", + "resolved": "https://registry.npmjs.org/mime-types/-/mime-types-2.1.35.tgz", + "integrity": "sha512-ZDY+bPm5zTTF+YpCrAU9nK0UgICYPT0QtT1NZWFv4s++TNkcgVaT0g6+4R2uI4MjQjzysHB1zxuWL50hzaeXiw==", + "license": "MIT", + "dependencies": { + "mime-db": "1.52.0" + }, + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/mimic-fn": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/mimic-fn/-/mimic-fn-2.1.0.tgz", + "integrity": "sha512-OqbOk5oEQeAZ8WXWydlu9HJjz9WVdEIvamMCcXmuqUYjTknH/sqsWvhQ3vgwKFRR1HpjvNBKQ37nbJgYzGqGcg==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=6" + } + }, + "node_modules/minimatch": { + "version": "3.1.5", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.5.tgz", + "integrity": "sha512-VgjWUsnnT6n+NUk6eZq77zeFdpW2LWDzP6zFGrCbHXiYNul5Dzqk2HHQ5uFH2DNW5Xbp8+jVzaeNt94ssEEl4w==", + "dev": true, + "license": "ISC", + "dependencies": { + "brace-expansion": "^1.1.7" + }, + "engines": { + "node": "*" + } + }, + "node_modules/minimist": { + "version": "1.2.8", + "resolved": "https://registry.npmjs.org/minimist/-/minimist-1.2.8.tgz", + "integrity": "sha512-2yyAR8qBkN3YuheJanUpWC5U3bb5osDywNB8RzDVlDwDHbocAJveqqj1u8+SVD7jkWT4yvsHCpWqqWqAxb0zCA==", + "dev": true, + "license": "MIT", + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/ms": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", + "integrity": "sha512-Tpp60P6IUJDTuOq/5Z8cdskzJujfwqfOTkrwIwj7IRISpnkJnT6SyJ4PCPnGMoFjC9ddhal5KVIYtAt97ix05A==", + "license": "MIT" + }, + "node_modules/natural-compare": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/natural-compare/-/natural-compare-1.4.0.tgz", + "integrity": "sha512-OWND8ei3VtNC9h7V60qff3SVobHr996CTwgxubgyQYEpg290h9J0buyECNNJexkFm5sOajh5G116RYA1c8ZMSw==", + "dev": true, + "license": "MIT" + }, + "node_modules/negotiator": { + "version": "0.6.3", + "resolved": "https://registry.npmjs.org/negotiator/-/negotiator-0.6.3.tgz", + "integrity": "sha512-+EUsqGPLsM+j/zdChZjsnX51g4XrHFOIXwfnCVPGlQk/k5giakcKsuxCObBRu6DSm9opw/O6slWbJdghQM4bBg==", + "license": "MIT", + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/neo-async": { + "version": "2.6.2", + "resolved": "https://registry.npmjs.org/neo-async/-/neo-async-2.6.2.tgz", + "integrity": "sha512-Yd3UES5mWCSqR+qNT93S3UoYUkqAZ9lLg8a7g9rimsWmYGK8cVToA4/sF3RrshdyV3sAGMXVUmpMYOw+dLpOuw==", + "dev": true, + "license": "MIT" + }, + "node_modules/node-int64": { + "version": "0.4.0", + "resolved": "https://registry.npmjs.org/node-int64/-/node-int64-0.4.0.tgz", + "integrity": "sha512-O5lz91xSOeoXP6DulyHfllpq+Eg00MWitZIbtPfoSEvqIHdl5gfcY6hYzDWnj0qD5tz52PI08u9qUvSVeUBeHw==", + "dev": true, + "license": "MIT" + }, + "node_modules/node-releases": { + "version": "2.0.36", + "resolved": "https://registry.npmjs.org/node-releases/-/node-releases-2.0.36.tgz", + "integrity": "sha512-TdC8FSgHz8Mwtw9g5L4gR/Sh9XhSP/0DEkQxfEFXOpiul5IiHgHan2VhYYb6agDSfp4KuvltmGApc8HMgUrIkA==", + "dev": true, + "license": "MIT" + }, + "node_modules/nodemon": { + "version": "3.1.14", + "resolved": "https://registry.npmjs.org/nodemon/-/nodemon-3.1.14.tgz", + "integrity": "sha512-jakjZi93UtB3jHMWsXL68FXSAosbLfY0In5gtKq3niLSkrWznrVBzXFNOEMJUfc9+Ke7SHWoAZsiMkNP3vq6Jw==", + "dev": true, + "license": "MIT", + "dependencies": { + "chokidar": "^3.5.2", + "debug": "^4", + "ignore-by-default": "^1.0.1", + "minimatch": "^10.2.1", + "pstree.remy": "^1.1.8", + "semver": "^7.5.3", + "simple-update-notifier": "^2.0.0", + "supports-color": "^5.5.0", + "touch": "^3.1.0", + "undefsafe": "^2.0.5" + }, + "bin": { + "nodemon": "bin/nodemon.js" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/nodemon" + } + }, + "node_modules/nodemon/node_modules/balanced-match": { + "version": "4.0.4", + "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-4.0.4.tgz", + "integrity": "sha512-BLrgEcRTwX2o6gGxGOCNyMvGSp35YofuYzw9h1IMTRmKqttAZZVU67bdb9Pr2vUHA8+j3i2tJfjO6C6+4myGTA==", + "dev": true, + "license": "MIT", + "engines": { + "node": "18 || 20 || >=22" + } + }, + "node_modules/nodemon/node_modules/brace-expansion": { + "version": "5.0.4", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-5.0.4.tgz", + "integrity": "sha512-h+DEnpVvxmfVefa4jFbCf5HdH5YMDXRsmKflpf1pILZWRFlTbJpxeU55nJl4Smt5HQaGzg1o6RHFPJaOqnmBDg==", + "dev": true, + "license": "MIT", + "dependencies": { + "balanced-match": "^4.0.2" + }, + "engines": { + "node": "18 || 20 || >=22" + } + }, + "node_modules/nodemon/node_modules/debug": { + "version": "4.4.3", + "resolved": "https://registry.npmjs.org/debug/-/debug-4.4.3.tgz", + "integrity": "sha512-RGwwWnwQvkVfavKVt22FGLw+xYSdzARwm0ru6DhTVA3umU5hZc28V3kO4stgYryrTlLpuvgI9GiijltAjNbcqA==", + "dev": true, + "license": "MIT", + "dependencies": { + "ms": "^2.1.3" + }, + "engines": { + "node": ">=6.0" + }, + "peerDependenciesMeta": { + "supports-color": { + "optional": true + } + } + }, + "node_modules/nodemon/node_modules/has-flag": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-3.0.0.tgz", + "integrity": "sha512-sKJf1+ceQBr4SMkvQnBDNDtf4TXpVhVGateu0t918bl30FnbE2m4vNLX+VWe/dpjlb+HugGYzW7uQXH98HPEYw==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=4" + } + }, + "node_modules/nodemon/node_modules/minimatch": { + "version": "10.2.4", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-10.2.4.tgz", + "integrity": "sha512-oRjTw/97aTBN0RHbYCdtF1MQfvusSIBQM0IZEgzl6426+8jSC0nF1a/GmnVLpfB9yyr6g6FTqWqiZVbxrtaCIg==", + "dev": true, + "license": "BlueOak-1.0.0", + "dependencies": { + "brace-expansion": "^5.0.2" + }, + "engines": { + "node": "18 || 20 || >=22" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, + "node_modules/nodemon/node_modules/ms": { + "version": "2.1.3", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.3.tgz", + "integrity": "sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==", + "dev": true, + "license": "MIT" + }, + "node_modules/nodemon/node_modules/semver": { + "version": "7.7.4", + "resolved": "https://registry.npmjs.org/semver/-/semver-7.7.4.tgz", + "integrity": "sha512-vFKC2IEtQnVhpT78h1Yp8wzwrf8CM+MzKMHGJZfBtzhZNycRFnXsHk6E5TxIkkMsgNS7mdX3AGB7x2QM2di4lA==", + "dev": true, + "license": "ISC", + "bin": { + "semver": "bin/semver.js" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/nodemon/node_modules/supports-color": { + "version": "5.5.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-5.5.0.tgz", + "integrity": "sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow==", + "dev": true, + "license": "MIT", + "dependencies": { + "has-flag": "^3.0.0" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/normalize-path": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/normalize-path/-/normalize-path-3.0.0.tgz", + "integrity": "sha512-6eZs5Ls3WtCisHWp9S2GUy8dqkpGi4BVSz3GaqiE6ezub0512ESztXUwUB6C6IKbQkY2Pnb/mD4WYojCRwcwLA==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/npm-run-path": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/npm-run-path/-/npm-run-path-4.0.1.tgz", + "integrity": "sha512-S48WzZW777zhNIrn7gxOlISNAqi9ZC/uQFnRdbeIHhZhCA6UqpkOT8T1G7BvfdgP4Er8gF4sUbaS0i7QvIfCWw==", + "dev": true, + "license": "MIT", + "dependencies": { + "path-key": "^3.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/object-assign": { + "version": "4.1.1", + "resolved": "https://registry.npmjs.org/object-assign/-/object-assign-4.1.1.tgz", + "integrity": "sha512-rJgTQnkUnH1sFw8yT6VSU3zD3sWmu6sZhIseY8VX+GRu3P6F7Fu+JNDoXfklElbLJSnc3FUQHVe4cU5hj+BcUg==", + "license": "MIT", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/object-inspect": { + "version": "1.13.4", + "resolved": "https://registry.npmjs.org/object-inspect/-/object-inspect-1.13.4.tgz", + "integrity": "sha512-W67iLl4J2EXEGTbfeHCffrjDfitvLANg0UlX3wFUUSTx92KXRFegMHUVgSqE+wvhAbi4WqjGg9czysTV2Epbew==", + "license": "MIT", + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/on-finished": { + "version": "2.4.1", + "resolved": "https://registry.npmjs.org/on-finished/-/on-finished-2.4.1.tgz", + "integrity": "sha512-oVlzkg3ENAhCk2zdv7IJwd/QUD4z2RxRwpkcGY8psCVcCYZNq4wYnVWALHM+brtuJjePWiYF/ClmuDr8Ch5+kg==", + "license": "MIT", + "dependencies": { + "ee-first": "1.1.1" + }, + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/once": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/once/-/once-1.4.0.tgz", + "integrity": "sha512-lNaJgI+2Q5URQBkccEKHTQOPaXdUxnZZElQTZY0MFUAuaEqe1E+Nyvgdz/aIyNi6Z9MzO5dv1H8n58/GELp3+w==", + "dev": true, + "license": "ISC", + "dependencies": { + "wrappy": "1" + } + }, + "node_modules/onetime": { + "version": "5.1.2", + "resolved": "https://registry.npmjs.org/onetime/-/onetime-5.1.2.tgz", + "integrity": "sha512-kbpaSSGJTWdAY5KPVeMOKXSrPtr8C8C7wodJbcsd51jRnmD+GZu8Y0VoU6Dm5Z4vWr0Ig/1NKuWRKf7j5aaYSg==", + "dev": true, + "license": "MIT", + "dependencies": { + "mimic-fn": "^2.1.0" + }, + "engines": { + "node": ">=6" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/p-limit": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-3.1.0.tgz", + "integrity": "sha512-TYOanM3wGwNGsZN2cVTYPArw454xnXj5qmWF1bEoAc4+cU/ol7GVh7odevjp1FNHduHc3KZMcFduxU5Xc6uJRQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "yocto-queue": "^0.1.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/p-locate": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-4.1.0.tgz", + "integrity": "sha512-R79ZZ/0wAxKGu3oYMlz8jy/kbhsNrS7SKZ7PxEHBgJ5+F2mtFW2fK2cOtBh1cHYkQsbzFV7I+EoRKe6Yt0oK7A==", + "dev": true, + "license": "MIT", + "dependencies": { + "p-limit": "^2.2.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/p-locate/node_modules/p-limit": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-2.3.0.tgz", + "integrity": "sha512-//88mFWSJx8lxCzwdAABTJL2MyWB12+eIY7MDL2SqLmAkeKU9qxRvWuSyTjm3FUmpBEMuFfckAIqEaVGUDxb6w==", + "dev": true, + "license": "MIT", + "dependencies": { + "p-try": "^2.0.0" + }, + "engines": { + "node": ">=6" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/p-try": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/p-try/-/p-try-2.2.0.tgz", + "integrity": "sha512-R4nPAVTAU0B9D35/Gk3uJf/7XYbQcyohSKdvAxIRSNghFl4e71hVoGnBNQz9cWaXxO2I10KTC+3jMdvvoKw6dQ==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=6" + } + }, + "node_modules/parse-json": { + "version": "5.2.0", + "resolved": "https://registry.npmjs.org/parse-json/-/parse-json-5.2.0.tgz", + "integrity": "sha512-ayCKvm/phCGxOkYRSCM82iDwct8/EonSEgCSxWxD7ve6jHggsFl4fZVQBPRNgQoKiuV/odhFrGzQXZwbifC8Rg==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/code-frame": "^7.0.0", + "error-ex": "^1.3.1", + "json-parse-even-better-errors": "^2.3.0", + "lines-and-columns": "^1.1.6" + }, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/parseurl": { + "version": "1.3.3", + "resolved": "https://registry.npmjs.org/parseurl/-/parseurl-1.3.3.tgz", + "integrity": "sha512-CiyeOxFT/JZyN5m0z9PfXw4SCBJ6Sygz1Dpl0wqjlhDEGGBP1GnsUVEL0p63hoG1fcj3fHynXi9NYO4nWOL+qQ==", + "license": "MIT", + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/path-exists": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/path-exists/-/path-exists-4.0.0.tgz", + "integrity": "sha512-ak9Qy5Q7jYb2Wwcey5Fpvg2KoAc/ZIhLSLOSBmRmygPsGwkVVt0fZa0qrtMz+m6tJTAHfZQ8FnmB4MG4LWy7/w==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=8" + } + }, + "node_modules/path-is-absolute": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/path-is-absolute/-/path-is-absolute-1.0.1.tgz", + "integrity": "sha512-AVbw3UJ2e9bq64vSaS9Am0fje1Pa8pbGqTTsmXfaIiMpnr5DlDhfJOuLj9Sf95ZPVDAUerDfEk88MPmPe7UCQg==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/path-key": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/path-key/-/path-key-3.1.1.tgz", + "integrity": "sha512-ojmeN0qd+y0jszEtoY48r0Peq5dwMEkIlCOu6Q5f41lfkswXuKtYrhgoTpLnyIcHm24Uhqx+5Tqm2InSwLhE6Q==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=8" + } + }, + "node_modules/path-parse": { + "version": "1.0.7", + "resolved": "https://registry.npmjs.org/path-parse/-/path-parse-1.0.7.tgz", + "integrity": "sha512-LDJzPVEEEPR+y48z93A0Ed0yXb8pAByGWo/k5YYdYgpY2/2EsOsksJrq7lOHxryrVOn1ejG6oAp8ahvOIQD8sw==", + "dev": true, + "license": "MIT" + }, + "node_modules/path-to-regexp": { + "version": "0.1.12", + "resolved": "https://registry.npmjs.org/path-to-regexp/-/path-to-regexp-0.1.12.tgz", + "integrity": "sha512-RA1GjUVMnvYFxuqovrEqZoxxW5NUZqbwKtYz/Tt7nXerk0LbLblQmrsgdeOxV5SFHf0UDggjS/bSeOZwt1pmEQ==", + "license": "MIT" + }, + "node_modules/picocolors": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/picocolors/-/picocolors-1.1.1.tgz", + "integrity": "sha512-xceH2snhtb5M9liqDsmEw56le376mTZkEX/jEb/RxNFyegNul7eNslCXP9FDj/Lcu0X8KEyMceP2ntpaHrDEVA==", + "dev": true, + "license": "ISC" + }, + "node_modules/picomatch": { + "version": "2.3.1", + "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-2.3.1.tgz", + "integrity": "sha512-JU3teHTNjmE2VCGFzuY8EXzCDVwEqB2a8fsIvwaStHhAWJEeVd1o1QD80CU6+ZdEXXSLbSsuLwJjkCBWqRQUVA==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=8.6" + }, + "funding": { + "url": "https://github.com/sponsors/jonschlinkert" + } + }, + "node_modules/pirates": { + "version": "4.0.7", + "resolved": "https://registry.npmjs.org/pirates/-/pirates-4.0.7.tgz", + "integrity": "sha512-TfySrs/5nm8fQJDcBDuUng3VOUKsd7S+zqvbOTiGXHfxX4wK31ard+hoNuvkicM/2YFzlpDgABOevKSsB4G/FA==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">= 6" + } + }, + "node_modules/pkg-dir": { + "version": "4.2.0", + "resolved": "https://registry.npmjs.org/pkg-dir/-/pkg-dir-4.2.0.tgz", + "integrity": "sha512-HRDzbaKjC+AOWVXxAU/x54COGeIv9eb+6CkDSQoNTt4XyWoIJvuPsXizxu/Fr23EiekbtZwmh1IcIG/l/a10GQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "find-up": "^4.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/pretty-format": { + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/pretty-format/-/pretty-format-29.7.0.tgz", + "integrity": "sha512-Pdlw/oPxN+aXdmM9R00JVC9WVFoCLTKJvDVLgmJ+qAffBMxsV85l/Lu7sNx4zSzPyoL2euImuEwHhOXdEgNFZQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "@jest/schemas": "^29.6.3", + "ansi-styles": "^5.0.0", + "react-is": "^18.0.0" + }, + "engines": { + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + } + }, + "node_modules/pretty-format/node_modules/ansi-styles": { + "version": "5.2.0", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-5.2.0.tgz", + "integrity": "sha512-Cxwpt2SfTzTtXcfOlzGEee8O+c+MmUgGrNiBcXnuWxuFJHe6a5Hz7qwhwe5OgaSYI0IJvkLqWX1ASG+cJOkEiA==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/chalk/ansi-styles?sponsor=1" + } + }, + "node_modules/prompts": { + "version": "2.4.2", + "resolved": "https://registry.npmjs.org/prompts/-/prompts-2.4.2.tgz", + "integrity": "sha512-NxNv/kLguCA7p3jE8oL2aEBsrJWgAakBpgmgK6lpPWV+WuOmY6r2/zbAVnP+T8bQlA0nzHXSJSJW0Hq7ylaD2Q==", + "dev": true, + "license": "MIT", + "dependencies": { + "kleur": "^3.0.3", + "sisteransi": "^1.0.5" + }, + "engines": { + "node": ">= 6" + } + }, + "node_modules/proxy-addr": { + "version": "2.0.7", + "resolved": "https://registry.npmjs.org/proxy-addr/-/proxy-addr-2.0.7.tgz", + "integrity": "sha512-llQsMLSUDUPT44jdrU/O37qlnifitDP+ZwrmmZcoSKyLKvtZxpyV0n2/bD/N4tBAAZ/gJEdZU7KMraoK1+XYAg==", + "license": "MIT", + "dependencies": { + "forwarded": "0.2.0", + "ipaddr.js": "1.9.1" + }, + "engines": { + "node": ">= 0.10" + } + }, + "node_modules/pstree.remy": { + "version": "1.1.8", + "resolved": "https://registry.npmjs.org/pstree.remy/-/pstree.remy-1.1.8.tgz", + "integrity": "sha512-77DZwxQmxKnu3aR542U+X8FypNzbfJ+C5XQDk3uWjWxn6151aIMGthWYRXTqT1E5oJvg+ljaa2OJi+VfvCOQ8w==", + "dev": true, + "license": "MIT" + }, + "node_modules/pure-rand": { + "version": "6.1.0", + "resolved": "https://registry.npmjs.org/pure-rand/-/pure-rand-6.1.0.tgz", + "integrity": "sha512-bVWawvoZoBYpp6yIoQtQXHZjmz35RSVHnUOTefl8Vcjr8snTPY1wnpSPMWekcFwbxI6gtmT7rSYPFvz71ldiOA==", + "dev": true, + "funding": [ + { + "type": "individual", + "url": "https://github.com/sponsors/dubzzz" + }, + { + "type": "opencollective", + "url": "https://opencollective.com/fast-check" + } + ], + "license": "MIT" + }, + "node_modules/qs": { + "version": "6.14.2", + "resolved": "https://registry.npmjs.org/qs/-/qs-6.14.2.tgz", + "integrity": "sha512-V/yCWTTF7VJ9hIh18Ugr2zhJMP01MY7c5kh4J870L7imm6/DIzBsNLTXzMwUA3yZ5b/KBqLx8Kp3uRvd7xSe3Q==", + "license": "BSD-3-Clause", + "dependencies": { + "side-channel": "^1.1.0" + }, + "engines": { + "node": ">=0.6" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/range-parser": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/range-parser/-/range-parser-1.2.1.tgz", + "integrity": "sha512-Hrgsx+orqoygnmhFbKaHE6c296J+HTAQXoxEF6gNupROmmGJRoyzfG3ccAveqCBrwr/2yxQ5BVd/GTl5agOwSg==", + "license": "MIT", + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/raw-body": { + "version": "2.5.3", + "resolved": "https://registry.npmjs.org/raw-body/-/raw-body-2.5.3.tgz", + "integrity": "sha512-s4VSOf6yN0rvbRZGxs8Om5CWj6seneMwK3oDb4lWDH0UPhWcxwOWw5+qk24bxq87szX1ydrwylIOp2uG1ojUpA==", + "license": "MIT", + "dependencies": { + "bytes": "~3.1.2", + "http-errors": "~2.0.1", + "iconv-lite": "~0.4.24", + "unpipe": "~1.0.0" + }, + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/react-is": { + "version": "18.3.1", + "resolved": "https://registry.npmjs.org/react-is/-/react-is-18.3.1.tgz", + "integrity": "sha512-/LLMVyas0ljjAtoYiPqYiL8VWXzUUdThrmU5+n20DZv+a+ClRoevUzw5JxU+Ieh5/c87ytoTBV9G1FiKfNJdmg==", + "dev": true, + "license": "MIT" + }, + "node_modules/readdirp": { + "version": "3.6.0", + "resolved": "https://registry.npmjs.org/readdirp/-/readdirp-3.6.0.tgz", + "integrity": "sha512-hOS089on8RduqdbhvQ5Z37A0ESjsqz6qnRcffsMU3495FuTdqSm+7bhJ29JvIOsBDEEnan5DPu9t3To9VRlMzA==", + "dev": true, + "license": "MIT", + "dependencies": { + "picomatch": "^2.2.1" + }, + "engines": { + "node": ">=8.10.0" + } + }, + "node_modules/require-directory": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/require-directory/-/require-directory-2.1.1.tgz", + "integrity": "sha512-fGxEI7+wsG9xrvdjsrlmL22OMTTiHRwAMroiEeMgq8gzoLC/PQr7RsRDSTLUg/bZAZtF+TVIkHc6/4RIKrui+Q==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/resolve": { + "version": "1.22.11", + "resolved": "https://registry.npmjs.org/resolve/-/resolve-1.22.11.tgz", + "integrity": "sha512-RfqAvLnMl313r7c9oclB1HhUEAezcpLjz95wFH4LVuhk9JF/r22qmVP9AMmOU4vMX7Q8pN8jwNg/CSpdFnMjTQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "is-core-module": "^2.16.1", + "path-parse": "^1.0.7", + "supports-preserve-symlinks-flag": "^1.0.0" + }, + "bin": { + "resolve": "bin/resolve" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/resolve-cwd": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/resolve-cwd/-/resolve-cwd-3.0.0.tgz", + "integrity": "sha512-OrZaX2Mb+rJCpH/6CpSqt9xFVpN++x01XnN2ie9g6P5/3xelLAkXWVADpdz1IHD/KFfEXyE6V0U01OQ3UO2rEg==", + "dev": true, + "license": "MIT", + "dependencies": { + "resolve-from": "^5.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/resolve-from": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/resolve-from/-/resolve-from-5.0.0.tgz", + "integrity": "sha512-qYg9KP24dD5qka9J47d0aVky0N+b4fTU89LN9iDnjB5waksiC49rvMB0PrUJQGoTmH50XPiqOvAjDfaijGxYZw==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=8" + } + }, + "node_modules/resolve.exports": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/resolve.exports/-/resolve.exports-2.0.3.tgz", + "integrity": "sha512-OcXjMsGdhL4XnbShKpAcSqPMzQoYkYyhbEaeSko47MjRP9NfEQMhZkXL1DoFlt9LWQn4YttrdnV6X2OiyzBi+A==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=10" + } + }, + "node_modules/safe-buffer": { + "version": "5.2.1", + "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.2.1.tgz", + "integrity": "sha512-rp3So07KcdmmKbGvgaNxQSJr7bGVSVk5S9Eq1F+ppbRo70+YeaDxkw5Dd8NPN+GD6bjnYm2VuPuCXmpuYvmCXQ==", + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/feross" + }, + { + "type": "patreon", + "url": "https://www.patreon.com/feross" + }, + { + "type": "consulting", + "url": "https://feross.org/support" + } + ], + "license": "MIT" + }, + "node_modules/safer-buffer": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/safer-buffer/-/safer-buffer-2.1.2.tgz", + "integrity": "sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg==", + "license": "MIT" + }, + "node_modules/semver": { + "version": "6.3.1", + "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.1.tgz", + "integrity": "sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA==", + "dev": true, + "license": "ISC", + "bin": { + "semver": "bin/semver.js" + } + }, + "node_modules/send": { + "version": "0.19.2", + "resolved": "https://registry.npmjs.org/send/-/send-0.19.2.tgz", + "integrity": "sha512-VMbMxbDeehAxpOtWJXlcUS5E8iXh6QmN+BkRX1GARS3wRaXEEgzCcB10gTQazO42tpNIya8xIyNx8fll1OFPrg==", + "license": "MIT", + "dependencies": { + "debug": "2.6.9", + "depd": "2.0.0", + "destroy": "1.2.0", + "encodeurl": "~2.0.0", + "escape-html": "~1.0.3", + "etag": "~1.8.1", + "fresh": "~0.5.2", + "http-errors": "~2.0.1", + "mime": "1.6.0", + "ms": "2.1.3", + "on-finished": "~2.4.1", + "range-parser": "~1.2.1", + "statuses": "~2.0.2" + }, + "engines": { + "node": ">= 0.8.0" + } + }, + "node_modules/send/node_modules/ms": { + "version": "2.1.3", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.3.tgz", + "integrity": "sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==", + "license": "MIT" + }, + "node_modules/serve-static": { + "version": "1.16.3", + "resolved": "https://registry.npmjs.org/serve-static/-/serve-static-1.16.3.tgz", + "integrity": "sha512-x0RTqQel6g5SY7Lg6ZreMmsOzncHFU7nhnRWkKgWuMTu5NN0DR5oruckMqRvacAN9d5w6ARnRBXl9xhDCgfMeA==", + "license": "MIT", + "dependencies": { + "encodeurl": "~2.0.0", + "escape-html": "~1.0.3", + "parseurl": "~1.3.3", + "send": "~0.19.1" + }, + "engines": { + "node": ">= 0.8.0" + } + }, + "node_modules/setprototypeof": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/setprototypeof/-/setprototypeof-1.2.0.tgz", + "integrity": "sha512-E5LDX7Wrp85Kil5bhZv46j8jOeboKq5JMmYM3gVGdGH8xFpPWXUMsNrlODCrkoxMEeNi/XZIwuRvY4XNwYMJpw==", + "license": "ISC" + }, + "node_modules/shebang-command": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/shebang-command/-/shebang-command-2.0.0.tgz", + "integrity": "sha512-kHxr2zZpYtdmrN1qDjrrX/Z1rR1kG8Dx+gkpK1G4eXmvXswmcE1hTWBWYUzlraYw1/yZp6YuDY77YtvbN0dmDA==", + "dev": true, + "license": "MIT", + "dependencies": { + "shebang-regex": "^3.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/shebang-regex": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/shebang-regex/-/shebang-regex-3.0.0.tgz", + "integrity": "sha512-7++dFhtcx3353uBaq8DDR4NuxBetBzC7ZQOhmTQInHEd6bSrXdiEyzCvG07Z44UYdLShWUyXt5M/yhz8ekcb1A==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=8" + } + }, + "node_modules/side-channel": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/side-channel/-/side-channel-1.1.0.tgz", + "integrity": "sha512-ZX99e6tRweoUXqR+VBrslhda51Nh5MTQwou5tnUDgbtyM0dBgmhEDtWGP/xbKn6hqfPRHujUNwz5fy/wbbhnpw==", + "license": "MIT", + "dependencies": { + "es-errors": "^1.3.0", + "object-inspect": "^1.13.3", + "side-channel-list": "^1.0.0", + "side-channel-map": "^1.0.1", + "side-channel-weakmap": "^1.0.2" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/side-channel-list": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/side-channel-list/-/side-channel-list-1.0.0.tgz", + "integrity": "sha512-FCLHtRD/gnpCiCHEiJLOwdmFP+wzCmDEkc9y7NsYxeF4u7Btsn1ZuwgwJGxImImHicJArLP4R0yX4c2KCrMrTA==", + "license": "MIT", + "dependencies": { + "es-errors": "^1.3.0", + "object-inspect": "^1.13.3" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/side-channel-map": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/side-channel-map/-/side-channel-map-1.0.1.tgz", + "integrity": "sha512-VCjCNfgMsby3tTdo02nbjtM/ewra6jPHmpThenkTYh8pG9ucZ/1P8So4u4FGBek/BjpOVsDCMoLA/iuBKIFXRA==", + "license": "MIT", + "dependencies": { + "call-bound": "^1.0.2", + "es-errors": "^1.3.0", + "get-intrinsic": "^1.2.5", + "object-inspect": "^1.13.3" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/side-channel-weakmap": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/side-channel-weakmap/-/side-channel-weakmap-1.0.2.tgz", + "integrity": "sha512-WPS/HvHQTYnHisLo9McqBHOJk2FkHO/tlpvldyrnem4aeQp4hai3gythswg6p01oSoTl58rcpiFAjF2br2Ak2A==", + "license": "MIT", + "dependencies": { + "call-bound": "^1.0.2", + "es-errors": "^1.3.0", + "get-intrinsic": "^1.2.5", + "object-inspect": "^1.13.3", + "side-channel-map": "^1.0.1" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/signal-exit": { + "version": "3.0.7", + "resolved": "https://registry.npmjs.org/signal-exit/-/signal-exit-3.0.7.tgz", + "integrity": "sha512-wnD2ZE+l+SPC/uoS0vXeE9L1+0wuaMqKlfz9AMUo38JsyLSBWSFcHR1Rri62LZc12vLr1gb3jl7iwQhgwpAbGQ==", + "dev": true, + "license": "ISC" + }, + "node_modules/simple-git": { + "version": "3.33.0", + "resolved": "https://registry.npmjs.org/simple-git/-/simple-git-3.33.0.tgz", + "integrity": "sha512-D4V/tGC2sjsoNhoMybKyGoE+v8A60hRawKQ1iFRA1zwuDgGZCBJ4ByOzZ5J8joBbi4Oam0qiPH+GhzmSBwbJng==", + "license": "MIT", + "dependencies": { + "@kwsites/file-exists": "^1.1.1", + "@kwsites/promise-deferred": "^1.1.1", + "debug": "^4.4.0" + }, + "funding": { + "type": "github", + "url": "https://github.com/steveukx/git-js?sponsor=1" + } + }, + "node_modules/simple-git/node_modules/debug": { + "version": "4.4.3", + "resolved": "https://registry.npmjs.org/debug/-/debug-4.4.3.tgz", + "integrity": "sha512-RGwwWnwQvkVfavKVt22FGLw+xYSdzARwm0ru6DhTVA3umU5hZc28V3kO4stgYryrTlLpuvgI9GiijltAjNbcqA==", + "license": "MIT", + "dependencies": { + "ms": "^2.1.3" + }, + "engines": { + "node": ">=6.0" + }, + "peerDependenciesMeta": { + "supports-color": { + "optional": true + } + } + }, + "node_modules/simple-git/node_modules/ms": { + "version": "2.1.3", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.3.tgz", + "integrity": "sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==", + "license": "MIT" + }, + "node_modules/simple-update-notifier": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/simple-update-notifier/-/simple-update-notifier-2.0.0.tgz", + "integrity": "sha512-a2B9Y0KlNXl9u/vsW6sTIu9vGEpfKu2wRV6l1H3XEas/0gUIzGzBoP/IouTcUQbm9JWZLH3COxyn03TYlFax6w==", + "dev": true, + "license": "MIT", + "dependencies": { + "semver": "^7.5.3" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/simple-update-notifier/node_modules/semver": { + "version": "7.7.4", + "resolved": "https://registry.npmjs.org/semver/-/semver-7.7.4.tgz", + "integrity": "sha512-vFKC2IEtQnVhpT78h1Yp8wzwrf8CM+MzKMHGJZfBtzhZNycRFnXsHk6E5TxIkkMsgNS7mdX3AGB7x2QM2di4lA==", + "dev": true, + "license": "ISC", + "bin": { + "semver": "bin/semver.js" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/sisteransi": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/sisteransi/-/sisteransi-1.0.5.tgz", + "integrity": "sha512-bLGGlR1QxBcynn2d5YmDX4MGjlZvy2MRBDRNHLJ8VI6l6+9FUiyTFNJ0IveOSP0bcXgVDPRcfGqA0pjaqUpfVg==", + "dev": true, + "license": "MIT" + }, + "node_modules/slash": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/slash/-/slash-3.0.0.tgz", + "integrity": "sha512-g9Q1haeby36OSStwb4ntCGGGaKsaVSjQ68fBxoQcutl5fS1vuY18H3wSt3jFyFtrkx+Kz0V1G85A4MyAdDMi2Q==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=8" + } + }, + "node_modules/source-map": { + "version": "0.6.1", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", + "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==", + "dev": true, + "license": "BSD-3-Clause", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/source-map-support": { + "version": "0.5.13", + "resolved": "https://registry.npmjs.org/source-map-support/-/source-map-support-0.5.13.tgz", + "integrity": "sha512-SHSKFHadjVA5oR4PPqhtAVdcBWwRYVd6g6cAXnIbRiIwc2EhPrTuKUBdSLvlEKyIP3GCf89fltvcZiP9MMFA1w==", + "dev": true, + "license": "MIT", + "dependencies": { + "buffer-from": "^1.0.0", + "source-map": "^0.6.0" + } + }, + "node_modules/sprintf-js": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/sprintf-js/-/sprintf-js-1.0.3.tgz", + "integrity": "sha512-D9cPgkvLlV3t3IzL0D0YLvGA9Ahk4PcvVwUbN0dSGr1aP0Nrt4AEnTUbuGvquEC0mA64Gqt1fzirlRs5ibXx8g==", + "dev": true, + "license": "BSD-3-Clause" + }, + "node_modules/stack-utils": { + "version": "2.0.6", + "resolved": "https://registry.npmjs.org/stack-utils/-/stack-utils-2.0.6.tgz", + "integrity": "sha512-XlkWvfIm6RmsWtNJx+uqtKLS8eqFbxUg0ZzLXqY0caEy9l7hruX8IpiDnjsLavoBgqCCR71TqWO8MaXYheJ3RQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "escape-string-regexp": "^2.0.0" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/statuses": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/statuses/-/statuses-2.0.2.tgz", + "integrity": "sha512-DvEy55V3DB7uknRo+4iOGT5fP1slR8wQohVdknigZPMpMstaKJQWhwiYBACJE3Ul2pTnATihhBYnRhZQHGBiRw==", + "license": "MIT", + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/string-length": { + "version": "4.0.2", + "resolved": "https://registry.npmjs.org/string-length/-/string-length-4.0.2.tgz", + "integrity": "sha512-+l6rNN5fYHNhZZy41RXsYptCjA2Igmq4EG7kZAYFQI1E1VTXarr6ZPXBg6eq7Y6eK4FEhY6AJlyuFIb/v/S0VQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "char-regex": "^1.0.2", + "strip-ansi": "^6.0.0" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/string-width": { + "version": "4.2.3", + "resolved": "https://registry.npmjs.org/string-width/-/string-width-4.2.3.tgz", + "integrity": "sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==", + "dev": true, + "license": "MIT", + "dependencies": { + "emoji-regex": "^8.0.0", + "is-fullwidth-code-point": "^3.0.0", + "strip-ansi": "^6.0.1" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/strip-ansi": { + "version": "6.0.1", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.1.tgz", + "integrity": "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==", + "dev": true, + "license": "MIT", + "dependencies": { + "ansi-regex": "^5.0.1" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/strip-bom": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/strip-bom/-/strip-bom-4.0.0.tgz", + "integrity": "sha512-3xurFv5tEgii33Zi8Jtp55wEIILR9eh34FAW00PZf+JnSsTmV/ioewSgQl97JHvgjoRGwPShsWm+IdrxB35d0w==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=8" + } + }, + "node_modules/strip-final-newline": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/strip-final-newline/-/strip-final-newline-2.0.0.tgz", + "integrity": "sha512-BrpvfNAE3dcvq7ll3xVumzjKjZQ5tI1sEUIKr3Uoks0XUl45St3FlatVqef9prk4jRDzhW6WZg+3bk93y6pLjA==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=6" + } + }, + "node_modules/strip-json-comments": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/strip-json-comments/-/strip-json-comments-3.1.1.tgz", + "integrity": "sha512-6fPc+R4ihwqP6N/aIv2f1gMH8lOVtWQHoqC4yK6oSDVVocumAsfCqjkXnqiYMhmMwS/mEHLp7Vehlt3ql6lEig==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/supports-color": { + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", + "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", + "dev": true, + "license": "MIT", + "dependencies": { + "has-flag": "^4.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/supports-preserve-symlinks-flag": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/supports-preserve-symlinks-flag/-/supports-preserve-symlinks-flag-1.0.0.tgz", + "integrity": "sha512-ot0WnXS9fgdkgIcePe6RHNk1WA8+muPa6cSjeR3V8K27q9BB1rTE3R1p7Hv0z1ZyAc8s6Vvv8DIyWf681MAt0w==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/test-exclude": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/test-exclude/-/test-exclude-6.0.0.tgz", + "integrity": "sha512-cAGWPIyOHU6zlmg88jwm7VRyXnMN7iV68OGAbYDk/Mh/xC/pzVPlQtY6ngoIH/5/tciuhGfvESU8GrHrcxD56w==", + "dev": true, + "license": "ISC", + "dependencies": { + "@istanbuljs/schema": "^0.1.2", + "glob": "^7.1.4", + "minimatch": "^3.0.4" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/tmpl": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/tmpl/-/tmpl-1.0.5.tgz", + "integrity": "sha512-3f0uOEAQwIqGuWW2MVzYg8fV/QNnc/IpuJNG837rLuczAaLVHslWHZQj4IGiEl5Hs3kkbhwL9Ab7Hrsmuj+Smw==", + "dev": true, + "license": "BSD-3-Clause" + }, + "node_modules/to-regex-range": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/to-regex-range/-/to-regex-range-5.0.1.tgz", + "integrity": "sha512-65P7iz6X5yEr1cwcgvQxbbIw7Uk3gOy5dIdtZ4rDveLqhrdJP+Li/Hx6tyK0NEb+2GCyneCMJiGqrADCSNk8sQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "is-number": "^7.0.0" + }, + "engines": { + "node": ">=8.0" + } + }, + "node_modules/toidentifier": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/toidentifier/-/toidentifier-1.0.1.tgz", + "integrity": "sha512-o5sSPKEkg/DIQNmH43V0/uerLrpzVedkUh8tGNvaeXpfpuwjKenlSox/2O/BTlZUtEe+JG7s5YhEz608PlAHRA==", + "license": "MIT", + "engines": { + "node": ">=0.6" + } + }, + "node_modules/touch": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/touch/-/touch-3.1.1.tgz", + "integrity": "sha512-r0eojU4bI8MnHr8c5bNo7lJDdI2qXlWWJk6a9EAFG7vbhTjElYhBVS3/miuE0uOuoLdb8Mc/rVfsmm6eo5o9GA==", + "dev": true, + "license": "ISC", + "bin": { + "nodetouch": "bin/nodetouch.js" + } + }, + "node_modules/ts-algebra": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/ts-algebra/-/ts-algebra-2.0.0.tgz", + "integrity": "sha512-FPAhNPFMrkwz76P7cdjdmiShwMynZYN6SgOujD1urY4oNm80Ou9oMdmbR45LotcKOXoy7wSmHkRFE6Mxbrhefw==", + "license": "MIT" + }, + "node_modules/ts-jest": { + "version": "29.4.6", + "resolved": "https://registry.npmjs.org/ts-jest/-/ts-jest-29.4.6.tgz", + "integrity": "sha512-fSpWtOO/1AjSNQguk43hb/JCo16oJDnMJf3CdEGNkqsEX3t0KX96xvyX1D7PfLCpVoKu4MfVrqUkFyblYoY4lA==", + "dev": true, + "license": "MIT", + "dependencies": { + "bs-logger": "^0.2.6", + "fast-json-stable-stringify": "^2.1.0", + "handlebars": "^4.7.8", + "json5": "^2.2.3", + "lodash.memoize": "^4.1.2", + "make-error": "^1.3.6", + "semver": "^7.7.3", + "type-fest": "^4.41.0", + "yargs-parser": "^21.1.1" + }, + "bin": { + "ts-jest": "cli.js" + }, + "engines": { + "node": "^14.15.0 || ^16.10.0 || ^18.0.0 || >=20.0.0" + }, + "peerDependencies": { + "@babel/core": ">=7.0.0-beta.0 <8", + "@jest/transform": "^29.0.0 || ^30.0.0", + "@jest/types": "^29.0.0 || ^30.0.0", + "babel-jest": "^29.0.0 || ^30.0.0", + "jest": "^29.0.0 || ^30.0.0", + "jest-util": "^29.0.0 || ^30.0.0", + "typescript": ">=4.3 <6" + }, + "peerDependenciesMeta": { + "@babel/core": { + "optional": true + }, + "@jest/transform": { + "optional": true + }, + "@jest/types": { + "optional": true + }, + "babel-jest": { + "optional": true + }, + "esbuild": { + "optional": true + }, + "jest-util": { + "optional": true + } + } + }, + "node_modules/ts-jest/node_modules/semver": { + "version": "7.7.4", + "resolved": "https://registry.npmjs.org/semver/-/semver-7.7.4.tgz", + "integrity": "sha512-vFKC2IEtQnVhpT78h1Yp8wzwrf8CM+MzKMHGJZfBtzhZNycRFnXsHk6E5TxIkkMsgNS7mdX3AGB7x2QM2di4lA==", + "dev": true, + "license": "ISC", + "bin": { + "semver": "bin/semver.js" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/ts-jest/node_modules/type-fest": { + "version": "4.41.0", + "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-4.41.0.tgz", + "integrity": "sha512-TeTSQ6H5YHvpqVwBRcnLDCBnDOHWYu7IvGbHT6N8AOymcr9PJGjc1GTtiWZTYg0NCgYwvnYWEkVChQAr9bjfwA==", + "dev": true, + "license": "(MIT OR CC0-1.0)", + "engines": { + "node": ">=16" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/ts-node": { + "version": "10.9.2", + "resolved": "https://registry.npmjs.org/ts-node/-/ts-node-10.9.2.tgz", + "integrity": "sha512-f0FFpIdcHgn8zcPSbf1dRevwt047YMnaiJM3u2w2RewrB+fob/zePZcrOyQoLMMO7aBIddLcQIEK5dYjkLnGrQ==", + "dev": true, + "license": "MIT", + "peer": true, + "dependencies": { + "@cspotcode/source-map-support": "^0.8.0", + "@tsconfig/node10": "^1.0.7", + "@tsconfig/node12": "^1.0.7", + "@tsconfig/node14": "^1.0.0", + "@tsconfig/node16": "^1.0.2", + "acorn": "^8.4.1", + "acorn-walk": "^8.1.1", + "arg": "^4.1.0", + "create-require": "^1.1.0", + "diff": "^4.0.1", + "make-error": "^1.1.1", + "v8-compile-cache-lib": "^3.0.1", + "yn": "3.1.1" + }, + "bin": { + "ts-node": "dist/bin.js", + "ts-node-cwd": "dist/bin-cwd.js", + "ts-node-esm": "dist/bin-esm.js", + "ts-node-script": "dist/bin-script.js", + "ts-node-transpile-only": "dist/bin-transpile.js", + "ts-script": "dist/bin-script-deprecated.js" + }, + "peerDependencies": { + "@swc/core": ">=1.2.50", + "@swc/wasm": ">=1.2.50", + "@types/node": "*", + "typescript": ">=2.7" + }, + "peerDependenciesMeta": { + "@swc/core": { + "optional": true + }, + "@swc/wasm": { + "optional": true + } + } + }, + "node_modules/type-detect": { + "version": "4.0.8", + "resolved": "https://registry.npmjs.org/type-detect/-/type-detect-4.0.8.tgz", + "integrity": "sha512-0fr/mIH1dlO+x7TlcMy+bIDqKPsw/70tVyeHW787goQjhmqaZe10uwLujubK9q9Lg6Fiho1KUKDYz0Z7k7g5/g==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=4" + } + }, + "node_modules/type-fest": { + "version": "0.21.3", + "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-0.21.3.tgz", + "integrity": "sha512-t0rzBq87m3fVcduHDUFhKmyyX+9eo6WQjZvf51Ea/M0Q7+T374Jp1aUiyUl0GKxp8M/OETVHSDvmkyPgvX+X2w==", + "dev": true, + "license": "(MIT OR CC0-1.0)", + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/type-is": { + "version": "1.6.18", + "resolved": "https://registry.npmjs.org/type-is/-/type-is-1.6.18.tgz", + "integrity": "sha512-TkRKr9sUTxEH8MdfuCSP7VizJyzRNMjj2J2do2Jr3Kym598JVdEksuzPQCnlFPW4ky9Q+iA+ma9BGm06XQBy8g==", + "license": "MIT", + "dependencies": { + "media-typer": "0.3.0", + "mime-types": "~2.1.24" + }, + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/typescript": { + "version": "5.9.3", + "resolved": "https://registry.npmjs.org/typescript/-/typescript-5.9.3.tgz", + "integrity": "sha512-jl1vZzPDinLr9eUt3J/t7V6FgNEw9QjvBPdysz9KfQDD41fQrC2Y4vKQdiaUpFT4bXlb1RHhLpp8wtm6M5TgSw==", + "dev": true, + "license": "Apache-2.0", + "peer": true, + "bin": { + "tsc": "bin/tsc", + "tsserver": "bin/tsserver" + }, + "engines": { + "node": ">=14.17" + } + }, + "node_modules/uglify-js": { + "version": "3.19.3", + "resolved": "https://registry.npmjs.org/uglify-js/-/uglify-js-3.19.3.tgz", + "integrity": "sha512-v3Xu+yuwBXisp6QYTcH4UbH+xYJXqnq2m/LtQVWKWzYc1iehYnLixoQDN9FH6/j9/oybfd6W9Ghwkl8+UMKTKQ==", + "dev": true, + "license": "BSD-2-Clause", + "optional": true, + "bin": { + "uglifyjs": "bin/uglifyjs" + }, + "engines": { + "node": ">=0.8.0" + } + }, + "node_modules/undefsafe": { + "version": "2.0.5", + "resolved": "https://registry.npmjs.org/undefsafe/-/undefsafe-2.0.5.tgz", + "integrity": "sha512-WxONCrssBM8TSPRqN5EmsjVrsv4A8X12J4ArBiiayv3DyyG3ZlIg6yysuuSYdZsVz3TKcTg2fd//Ujd4CHV1iA==", + "dev": true, + "license": "MIT" + }, + "node_modules/undici-types": { + "version": "6.21.0", + "resolved": "https://registry.npmjs.org/undici-types/-/undici-types-6.21.0.tgz", + "integrity": "sha512-iwDZqg0QAGrg9Rav5H4n0M64c3mkR59cJ6wQp+7C4nI0gsmExaedaYLNO44eT4AtBBwjbTiGPMlt2Md0T9H9JQ==", + "dev": true, + "license": "MIT" + }, + "node_modules/unpipe": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/unpipe/-/unpipe-1.0.0.tgz", + "integrity": "sha512-pjy2bYhSsufwWlKwPc+l3cN7+wuJlK6uz0YdJEOlQDbl6jo/YlPi4mb8agUkVC8BF7V8NuzeyPNqRksA3hztKQ==", + "license": "MIT", + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/update-browserslist-db": { + "version": "1.2.3", + "resolved": "https://registry.npmjs.org/update-browserslist-db/-/update-browserslist-db-1.2.3.tgz", + "integrity": "sha512-Js0m9cx+qOgDxo0eMiFGEueWztz+d4+M3rGlmKPT+T4IS/jP4ylw3Nwpu6cpTTP8R1MAC1kF4VbdLt3ARf209w==", + "dev": true, + "funding": [ + { + "type": "opencollective", + "url": "https://opencollective.com/browserslist" + }, + { + "type": "tidelift", + "url": "https://tidelift.com/funding/github/npm/browserslist" + }, + { + "type": "github", + "url": "https://github.com/sponsors/ai" + } + ], + "license": "MIT", + "dependencies": { + "escalade": "^3.2.0", + "picocolors": "^1.1.1" + }, + "bin": { + "update-browserslist-db": "cli.js" + }, + "peerDependencies": { + "browserslist": ">= 4.21.0" + } + }, + "node_modules/utils-merge": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/utils-merge/-/utils-merge-1.0.1.tgz", + "integrity": "sha512-pMZTvIkT1d+TFGvDOqodOclx0QWkkgi6Tdoa8gC8ffGAAqz9pzPTZWAybbsHHoED/ztMtkv/VoYTYyShUn81hA==", + "license": "MIT", + "engines": { + "node": ">= 0.4.0" + } + }, + "node_modules/uuid": { + "version": "10.0.0", + "resolved": "https://registry.npmjs.org/uuid/-/uuid-10.0.0.tgz", + "integrity": "sha512-8XkAphELsDnEGrDxUOHB3RGvXz6TeuYSGEZBOjtTtPm2lwhGBjLgOzLHB63IUWfBpNucQjND6d3AOudO+H3RWQ==", + "funding": [ + "https://github.com/sponsors/broofa", + "https://github.com/sponsors/ctavan" + ], + "license": "MIT", + "bin": { + "uuid": "dist/bin/uuid" + } + }, + "node_modules/v8-compile-cache-lib": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/v8-compile-cache-lib/-/v8-compile-cache-lib-3.0.1.tgz", + "integrity": "sha512-wa7YjyUGfNZngI/vtK0UHAN+lgDCxBPCylVXGp0zu59Fz5aiGtNXaq3DhIov063MorB+VfufLh3JlF2KdTK3xg==", + "dev": true, + "license": "MIT" + }, + "node_modules/v8-to-istanbul": { + "version": "9.3.0", + "resolved": "https://registry.npmjs.org/v8-to-istanbul/-/v8-to-istanbul-9.3.0.tgz", + "integrity": "sha512-kiGUalWN+rgBJ/1OHZsBtU4rXZOfj/7rKQxULKlIzwzQSvMJUUNgPwJEEh7gU6xEVxC0ahoOBvN2YI8GH6FNgA==", + "dev": true, + "license": "ISC", + "dependencies": { + "@jridgewell/trace-mapping": "^0.3.12", + "@types/istanbul-lib-coverage": "^2.0.1", + "convert-source-map": "^2.0.0" + }, + "engines": { + "node": ">=10.12.0" + } + }, + "node_modules/vary": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/vary/-/vary-1.1.2.tgz", + "integrity": "sha512-BNGbWLfd0eUPabhkXUVm0j8uuvREyTh5ovRa/dyow/BqAbZJyC+5fU+IzQOzmAKzYqYRAISoRhdQr3eIZ/PXqg==", + "license": "MIT", + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/walker": { + "version": "1.0.8", + "resolved": "https://registry.npmjs.org/walker/-/walker-1.0.8.tgz", + "integrity": "sha512-ts/8E8l5b7kY0vlWLewOkDXMmPdLcVV4GmOQLyxuSswIJsweeFZtAsMF7k1Nszz+TYBQrlYRmzOnr398y1JemQ==", + "dev": true, + "license": "Apache-2.0", + "dependencies": { + "makeerror": "1.0.12" + } + }, + "node_modules/which": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/which/-/which-2.0.2.tgz", + "integrity": "sha512-BLI3Tl1TW3Pvl70l3yq3Y64i+awpwXqsGBYWkkqMtnbXgrMD+yj7rhW0kuEDxzJaYXGjEW5ogapKNMEKNMjibA==", + "dev": true, + "license": "ISC", + "dependencies": { + "isexe": "^2.0.0" + }, + "bin": { + "node-which": "bin/node-which" + }, + "engines": { + "node": ">= 8" + } + }, + "node_modules/wordwrap": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/wordwrap/-/wordwrap-1.0.0.tgz", + "integrity": "sha512-gvVzJFlPycKc5dZN4yPkP8w7Dc37BtP1yczEneOb4uq34pXZcvrtRTmWV8W+Ume+XCxKgbjM+nevkyFPMybd4Q==", + "dev": true, + "license": "MIT" + }, + "node_modules/wrap-ansi": { + "version": "7.0.0", + "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-7.0.0.tgz", + "integrity": "sha512-YVGIj2kamLSTxw6NsZjoBxfSwsn0ycdesmc4p+Q21c5zPuZ1pl+NfxVdxPtdHvmNVOQ6XSYG4AUtyt/Fi7D16Q==", + "dev": true, + "license": "MIT", + "dependencies": { + "ansi-styles": "^4.0.0", + "string-width": "^4.1.0", + "strip-ansi": "^6.0.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/chalk/wrap-ansi?sponsor=1" + } + }, + "node_modules/wrappy": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/wrappy/-/wrappy-1.0.2.tgz", + "integrity": "sha512-l4Sp/DRseor9wL6EvV2+TuQn63dMkPjZ/sp9XkghTEbV9KlPS1xUsZ3u7/IQO4wxtcFB4bgpQPRcR3QCvezPcQ==", + "dev": true, + "license": "ISC" + }, + "node_modules/write-file-atomic": { + "version": "4.0.2", + "resolved": "https://registry.npmjs.org/write-file-atomic/-/write-file-atomic-4.0.2.tgz", + "integrity": "sha512-7KxauUdBmSdWnmpaGFg+ppNjKF8uNLry8LyzjauQDOVONfFLNKrKvQOxZ/VuTIcS/gge/YNahf5RIIQWTSarlg==", + "dev": true, + "license": "ISC", + "dependencies": { + "imurmurhash": "^0.1.4", + "signal-exit": "^3.0.7" + }, + "engines": { + "node": "^12.13.0 || ^14.15.0 || >=16.0.0" + } + }, + "node_modules/ws": { + "version": "8.19.0", + "resolved": "https://registry.npmjs.org/ws/-/ws-8.19.0.tgz", + "integrity": "sha512-blAT2mjOEIi0ZzruJfIhb3nps74PRWTCz1IjglWEEpQl5XS/UNama6u2/rjFkDDouqr4L67ry+1aGIALViWjDg==", + "license": "MIT", + "engines": { + "node": ">=10.0.0" + }, + "peerDependencies": { + "bufferutil": "^4.0.1", + "utf-8-validate": ">=5.0.2" + }, + "peerDependenciesMeta": { + "bufferutil": { + "optional": true + }, + "utf-8-validate": { + "optional": true + } + } + }, + "node_modules/y18n": { + "version": "5.0.8", + "resolved": "https://registry.npmjs.org/y18n/-/y18n-5.0.8.tgz", + "integrity": "sha512-0pfFzegeDWJHJIAmTLRP2DwHjdF5s7jo9tuztdQxAhINCdvS+3nGINqPd00AphqJR/0LhANUS6/+7SCb98YOfA==", + "dev": true, + "license": "ISC", + "engines": { + "node": ">=10" + } + }, + "node_modules/yallist": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/yallist/-/yallist-3.1.1.tgz", + "integrity": "sha512-a4UGQaWPH59mOXUYnAG2ewncQS4i4F43Tv3JoAM+s2VDAmS9NsK8GpDMLrCHPksFT7h3K6TOoUNn2pb7RoXx4g==", + "dev": true, + "license": "ISC" + }, + "node_modules/yargs": { + "version": "17.7.2", + "resolved": "https://registry.npmjs.org/yargs/-/yargs-17.7.2.tgz", + "integrity": "sha512-7dSzzRQ++CKnNI/krKnYRV7JKKPUXMEh61soaHKg9mrWEhzFWhFnxPxGl+69cD1Ou63C13NUPCnmIcrvqCuM6w==", + "dev": true, + "license": "MIT", + "dependencies": { + "cliui": "^8.0.1", + "escalade": "^3.1.1", + "get-caller-file": "^2.0.5", + "require-directory": "^2.1.1", + "string-width": "^4.2.3", + "y18n": "^5.0.5", + "yargs-parser": "^21.1.1" + }, + "engines": { + "node": ">=12" + } + }, + "node_modules/yargs-parser": { + "version": "21.1.1", + "resolved": "https://registry.npmjs.org/yargs-parser/-/yargs-parser-21.1.1.tgz", + "integrity": "sha512-tVpsJW7DdjecAiFpbIB1e3qxIQsE6NoPc5/eTdrbbIC4h0LVsWhnoa3g+m2HclBIujHzsxZ4VJVA+GUuc2/LBw==", + "dev": true, + "license": "ISC", + "engines": { + "node": ">=12" + } + }, + "node_modules/yn": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/yn/-/yn-3.1.1.tgz", + "integrity": "sha512-Ux4ygGWsu2c7isFWe8Yu1YluJmqVhxqK2cLXNQA5AcC3QfbGNpM7fu0Y8b/z16pXLnFxZYvWhd3fhBY9DLmC6Q==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=6" + } + }, + "node_modules/yocto-queue": { + "version": "0.1.0", + "resolved": "https://registry.npmjs.org/yocto-queue/-/yocto-queue-0.1.0.tgz", + "integrity": "sha512-rVksvsnNCdJ/ohGc6xgPwyN8eheCxsiLM8mxuE/t/mOVqJewPuO1miLpTHQiRgTKCLexL4MeAFVagts7HmNZ2Q==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/zod": { + "version": "3.25.76", + "resolved": "https://registry.npmjs.org/zod/-/zod-3.25.76.tgz", + "integrity": "sha512-gzUt/qt81nXsFGKIFcC3YnfEAx5NkunCfnDlvuBSSFS02bcXu4Lmea0AFIUwbLWxWPx3d9p8S5QoaujKcNQxcQ==", + "license": "MIT", + "peer": true, + "funding": { + "url": "https://github.com/sponsors/colinhacks" + } + } + } +} diff --git a/packages/bridge/package.json b/packages/bridge/package.json index 47dfea8..81d14ce 100644 --- a/packages/bridge/package.json +++ b/packages/bridge/package.json @@ -1,15 +1,38 @@ { "name": "@recursor/bridge", "private": true, - "version": "0.0.0", - "description": "ReCursor bridge server (scaffold only).", + "version": "0.1.0", + "description": "ReCursor bridge server", "license": "MIT", "main": "dist/index.js", "scripts": { "build": "tsc -p tsconfig.json", - "typecheck": "tsc -p tsconfig.json --noEmit" + "typecheck": "tsc -p tsconfig.json --noEmit", + "dev": "nodemon --exec ts-node src/index.ts", + "start": "node dist/index.js", + "test": "jest" + }, + "dependencies": { + "express": "^4.21.1", + "ws": "^8.18.0", + "@anthropic-ai/sdk": "^0.79.0", + "dotenv": "^16.4.7", + "zod": "^3.23.8", + "uuid": "^10.0.0", + "simple-git": "^3.27.0", + "cors": "^2.8.5" }, "devDependencies": { - "typescript": "^5.6.0" + "typescript": "^5.6.0", + "@types/express": "^5.0.0", + "@types/ws": "^8.5.13", + "@types/node": "^22.0.0", + "@types/uuid": "^10.0.0", + "@types/cors": "^2.8.17", + "ts-node": "^10.9.2", + "nodemon": "^3.1.7", + "jest": "^29.7.0", + "@types/jest": "^29.5.14", + "ts-jest": "^29.2.5" } } diff --git a/packages/bridge/src/agents/agent_sdk_adapter.ts b/packages/bridge/src/agents/agent_sdk_adapter.ts new file mode 100644 index 0000000..4dd8e81 --- /dev/null +++ b/packages/bridge/src/agents/agent_sdk_adapter.ts @@ -0,0 +1,134 @@ +import { v4 as uuidv4 } from "uuid"; +import { AgentSessionManager } from "./session_manager"; +import type { ConnectionManager } from "../websocket/connection_manager"; +import type { + SessionStartPayload, + MessagePayload, + ApprovalResponsePayload, + SessionEndPayload, + BridgeMessage, + SessionReadyPayload, + ErrorPayload, +} from "../types"; + +function log(msg: string): void { + console.log(`[${new Date().toISOString()}] [AgentSdkAdapter] ${msg}`); +} + +function ts(): string { + return new Date().toISOString(); +} + +export class AgentSdkAdapter { + private sessionManager: AgentSessionManager; + private connectionManager: ConnectionManager; + + constructor( + sessionManager: AgentSessionManager, + connectionManager: ConnectionManager + ) { + this.sessionManager = sessionManager; + this.connectionManager = connectionManager; + } + + async handleSessionStart( + payload: SessionStartPayload, + clientId: string + ): Promise { + try { + const sessionId = await this.sessionManager.createSession({ + sessionId: payload.session_id, + workingDirectory: payload.working_directory, + systemPrompt: payload.system_prompt, + model: payload.model, + }); + + this.connectionManager.addSessionToClient(clientId, sessionId); + + const sessions = this.sessionManager.getActiveSessions(); + const session = sessions.find((s) => s.id === sessionId); + + const readyMsg: BridgeMessage = { + type: "session_ready", + id: uuidv4(), + timestamp: ts(), + payload: { + session_id: sessionId, + model: session?.model ?? "unknown", + }, + }; + this.connectionManager.sendToClient(clientId, readyMsg); + log(`Session started: ${sessionId} for client ${clientId}`); + } catch (err) { + log(`Failed to start session: ${String(err)}`); + const errorMsg: BridgeMessage = { + type: "error", + id: uuidv4(), + timestamp: ts(), + payload: { + code: "SESSION_START_FAILED", + message: String(err), + request_type: "session_start", + }, + }; + this.connectionManager.sendToClient(clientId, errorMsg); + } + } + + async handleMessage( + payload: MessagePayload, + clientId: string + ): Promise { + try { + await this.sessionManager.sendMessage( + payload.session_id, + payload.content, + clientId + ); + } catch (err) { + log(`Failed to send message: ${String(err)}`); + const errorMsg: BridgeMessage = { + type: "error", + id: uuidv4(), + timestamp: ts(), + payload: { + code: "MESSAGE_FAILED", + message: String(err), + request_type: "message", + }, + }; + this.connectionManager.sendToClient(clientId, errorMsg); + } + } + + async handleApprovalResponse( + payload: ApprovalResponsePayload, + clientId: string + ): Promise { + try { + await this.sessionManager.executeToolCall( + payload.session_id, + payload.tool_call_id, + payload.decision + ); + } catch (err) { + log(`Failed to handle approval response: ${String(err)}`); + const errorMsg: BridgeMessage = { + type: "error", + id: uuidv4(), + timestamp: ts(), + payload: { + code: "APPROVAL_FAILED", + message: String(err), + request_type: "approval_response", + }, + }; + this.connectionManager.sendToClient(clientId, errorMsg); + } + } + + handleSessionEnd(payload: SessionEndPayload): void { + this.sessionManager.closeSession(payload.session_id); + log(`Session ended: ${payload.session_id}`); + } +} diff --git a/packages/bridge/src/agents/session_manager.ts b/packages/bridge/src/agents/session_manager.ts new file mode 100644 index 0000000..abed79f --- /dev/null +++ b/packages/bridge/src/agents/session_manager.ts @@ -0,0 +1,217 @@ +import Anthropic from "@anthropic-ai/sdk"; +import { v4 as uuidv4 } from "uuid"; +import { config } from "../config"; +import { eventBus } from "../notifications/event_bus"; +import type { + AgentSession, + SessionConfig, + StreamStartPayload, + StreamChunkPayload, + StreamEndPayload, + ApprovalRequiredPayload, + ToolCallPayload, +} from "../types"; + +function log(msg: string): void { + console.log(`[${new Date().toISOString()}] [AgentSessionManager] ${msg}`); +} + +interface InternalSession { + meta: AgentSession; + history: Anthropic.MessageParam[]; + systemPrompt?: string; + pendingToolCalls: Map }>; +} + +export class AgentSessionManager { + private client: Anthropic; + private sessions = new Map(); + + constructor() { + this.client = new Anthropic({ apiKey: config.ANTHROPIC_API_KEY }); + } + + async createSession(sessionConfig: SessionConfig): Promise { + const sessionId = sessionConfig.sessionId ?? uuidv4(); + + const meta: AgentSession = { + id: sessionId, + model: sessionConfig.model ?? config.AGENT_MODEL, + working_directory: sessionConfig.workingDirectory ?? config.ALLOWED_PROJECT_ROOT, + created_at: new Date().toISOString(), + status: "idle", + }; + + const internal: InternalSession = { + meta, + history: [], + systemPrompt: sessionConfig.systemPrompt, + pendingToolCalls: new Map(), + }; + + this.sessions.set(sessionId, internal); + log(`Created session: ${sessionId}`); + + eventBus.emitTyped("session-event", { + type: "session_created", + session_id: sessionId, + model: meta.model, + }); + + return sessionId; + } + + async resumeSession(sessionId: string): Promise { + const session = this.sessions.get(sessionId); + if (!session) throw new Error(`Session not found: ${sessionId}`); + session.meta.status = "idle"; + log(`Resumed session: ${sessionId}`); + } + + closeSession(sessionId: string): void { + const session = this.sessions.get(sessionId); + if (!session) return; + session.meta.status = "closed"; + this.sessions.delete(sessionId); + log(`Closed session: ${sessionId}`); + eventBus.emitTyped("session-event", { + type: "session_closed", + session_id: sessionId, + }); + } + + async sendMessage( + sessionId: string, + content: string, + clientId: string + ): Promise { + const session = this.sessions.get(sessionId); + if (!session) throw new Error(`Session not found: ${sessionId}`); + + session.meta.status = "active"; + session.history.push({ role: "user", content }); + + const messageId = uuidv4(); + + const startPayload: StreamStartPayload = { + session_id: sessionId, + message_id: messageId, + }; + eventBus.emitTyped("session-event", { type: "stream_start", ...startPayload, client_id: clientId }); + + try { + const streamParams: Anthropic.MessageStreamParams = { + model: session.meta.model, + max_tokens: 8192, + messages: session.history, + stream: true, + }; + + if (session.systemPrompt) { + (streamParams as Record)["system"] = session.systemPrompt; + } + + const stream = this.client.messages.stream(streamParams); + + let fullText = ""; + let chunkIndex = 0; + let stopReason = "end_turn"; + + for await (const event of stream) { + if (event.type === "content_block_delta") { + const delta = event.delta; + if (delta.type === "text_delta") { + const chunk = delta.text; + fullText += chunk; + + const chunkPayload: StreamChunkPayload = { + session_id: sessionId, + message_id: messageId, + delta: chunk, + index: chunkIndex++, + }; + eventBus.emitTyped("stream-chunk", chunkPayload); + } + } else if (event.type === "content_block_start") { + const block = event.content_block; + if (block.type === "tool_use") { + session.pendingToolCalls.set(block.id, { + toolName: block.name, + toolInput: block.input as Record, + }); + + const approvalPayload: ApprovalRequiredPayload = { + session_id: sessionId, + tool_call_id: block.id, + tool_name: block.name, + tool_input: block.input as Record, + message: `Tool call requested: ${block.name}`, + }; + eventBus.emitTyped("tool-event", { type: "approval_required", ...approvalPayload, client_id: clientId }); + } + } else if (event.type === "message_delta") { + if (event.delta.stop_reason) { + stopReason = event.delta.stop_reason; + } + } + } + + const finalMsg = await stream.finalMessage(); + session.history.push({ role: "assistant", content: finalMsg.content }); + + session.meta.status = "idle"; + + const endPayload: StreamEndPayload = { + session_id: sessionId, + message_id: messageId, + stop_reason: stopReason, + }; + eventBus.emitTyped("session-event", { type: "stream_end", ...endPayload, client_id: clientId }); + } catch (err) { + session.meta.status = "idle"; + log(`Stream error in session ${sessionId}: ${String(err)}`); + throw err; + } + } + + async executeToolCall( + sessionId: string, + toolCallId: string, + decision: string + ): Promise { + const session = this.sessions.get(sessionId); + if (!session) throw new Error(`Session not found: ${sessionId}`); + + const pending = session.pendingToolCalls.get(toolCallId); + if (!pending) { + log(`Tool call not found: ${toolCallId}`); + return; + } + + session.pendingToolCalls.delete(toolCallId); + + if (decision === "reject") { + log(`Tool call rejected: ${toolCallId}`); + eventBus.emitTyped("tool-event", { + type: "tool_rejected", + session_id: sessionId, + tool_call_id: toolCallId, + }); + return; + } + + log(`Tool call approved: ${toolCallId} (${pending.toolName})`); + eventBus.emitTyped("tool-event", { + type: "tool_approved", + session_id: sessionId, + tool_call_id: toolCallId, + tool_name: pending.toolName, + }); + } + + getActiveSessions(): AgentSession[] { + return Array.from(this.sessions.values()) + .filter((s) => s.meta.status !== "closed") + .map((s) => s.meta); + } +} diff --git a/packages/bridge/src/agents/tool_executor.ts b/packages/bridge/src/agents/tool_executor.ts new file mode 100644 index 0000000..db2a45f --- /dev/null +++ b/packages/bridge/src/agents/tool_executor.ts @@ -0,0 +1,350 @@ +import fs from "fs"; +import path from "path"; +import { spawn } from "child_process"; +import { promisify } from "util"; +import { config } from "../config"; +import type { ToolResult } from "../types"; + +const readFileAsync = promisify(fs.readFile); +const writeFileAsync = promisify(fs.writeFile); +const readdirAsync = promisify(fs.readdir); +const statAsync = promisify(fs.stat); + +function log(msg: string): void { + console.log(`[${new Date().toISOString()}] [ToolExecutor] ${msg}`); +} + +const ALLOWED_COMMANDS = ["git", "flutter", "npm", "node", "dart"]; + +function isWithinAllowedRoot(filePath: string): boolean { + const resolved = path.resolve(filePath); + const allowed = path.resolve(config.ALLOWED_PROJECT_ROOT); + return resolved.startsWith(allowed + path.sep) || resolved === allowed; +} + +function resolveWithinRoot(filePath: string, workingDir: string): string { + const resolved = path.isAbsolute(filePath) + ? path.resolve(filePath) + : path.resolve(workingDir, filePath); + return resolved; +} + +export class ToolExecutor { + async execute( + tool: string, + params: Record, + workingDir: string + ): Promise { + const start = Date.now(); + + if (!isWithinAllowedRoot(workingDir)) { + return { + success: false, + content: "", + error: `Working directory is outside of allowed project root: ${workingDir}`, + durationMs: Date.now() - start, + }; + } + + try { + let result: ToolResult; + switch (tool) { + case "read_file": + result = await this.readFile(params, workingDir, start); + break; + case "edit_file": + result = await this.editFile(params, workingDir, start); + break; + case "bash_command": + result = await this.bashCommand(params, workingDir, start); + break; + case "glob": + result = await this.glob(params, workingDir, start); + break; + case "grep": + result = await this.grep(params, workingDir, start); + break; + case "list_files": + result = await this.listFiles(params, workingDir, start); + break; + default: + result = { + success: false, + content: "", + error: `Unknown tool: ${tool}`, + durationMs: Date.now() - start, + }; + } + return result; + } catch (err) { + return { + success: false, + content: "", + error: String(err), + durationMs: Date.now() - start, + }; + } + } + + private async readFile( + params: Record, + workingDir: string, + start: number + ): Promise { + const filePath = String(params["path"] ?? ""); + const resolved = resolveWithinRoot(filePath, workingDir); + + if (!isWithinAllowedRoot(resolved)) { + return { success: false, content: "", error: "Path outside allowed root", durationMs: Date.now() - start }; + } + + const content = await readFileAsync(resolved, "utf8"); + return { success: true, content, durationMs: Date.now() - start }; + } + + private async editFile( + params: Record, + workingDir: string, + start: number + ): Promise { + const filePath = String(params["path"] ?? ""); + const oldStr = String(params["old_string"] ?? ""); + const newStr = String(params["new_string"] ?? ""); + const resolved = resolveWithinRoot(filePath, workingDir); + + if (!isWithinAllowedRoot(resolved)) { + return { success: false, content: "", error: "Path outside allowed root", durationMs: Date.now() - start }; + } + + const original = await readFileAsync(resolved, "utf8"); + if (!original.includes(oldStr)) { + return { success: false, content: "", error: "old_string not found in file", durationMs: Date.now() - start }; + } + + const updated = original.replace(oldStr, newStr); + await writeFileAsync(resolved, updated, "utf8"); + return { success: true, content: "File updated successfully", durationMs: Date.now() - start }; + } + + private bashCommand( + params: Record, + workingDir: string, + start: number + ): Promise { + return new Promise((resolve) => { + const command = String(params["command"] ?? ""); + const parts = command.trim().split(/\s+/); + const executable = parts[0]; + + if (!ALLOWED_COMMANDS.includes(executable)) { + resolve({ + success: false, + content: "", + error: `Command not allowed: ${executable}. Allowed: ${ALLOWED_COMMANDS.join(", ")}`, + durationMs: Date.now() - start, + }); + return; + } + + const child = spawn(executable, parts.slice(1), { + cwd: workingDir, + env: process.env, + shell: false, + }); + + let stdout = ""; + let stderr = ""; + + child.stdout.on("data", (d: Buffer) => { stdout += d.toString(); }); + child.stderr.on("data", (d: Buffer) => { stderr += d.toString(); }); + + child.on("close", (code) => { + const success = code === 0; + resolve({ + success, + content: stdout, + error: success ? undefined : stderr || `Exit code: ${code}`, + durationMs: Date.now() - start, + }); + }); + + child.on("error", (err) => { + resolve({ + success: false, + content: "", + error: String(err), + durationMs: Date.now() - start, + }); + }); + }); + } + + private async glob( + params: Record, + workingDir: string, + start: number + ): Promise { + const pattern = String(params["pattern"] ?? "**/*"); + const baseDir = resolveWithinRoot( + String(params["base_dir"] ?? "."), + workingDir + ); + + if (!isWithinAllowedRoot(baseDir)) { + return { success: false, content: "", error: "Path outside allowed root", durationMs: Date.now() - start }; + } + + // Use native fs walk for glob + const results: string[] = []; + await this.walkGlob(baseDir, baseDir, pattern, results); + return { success: true, content: results.join("\n"), durationMs: Date.now() - start }; + } + + private async walkGlob( + base: string, + current: string, + pattern: string, + results: string[] + ): Promise { + let entries: string[]; + try { + entries = await readdirAsync(current); + } catch { + return; + } + + for (const entry of entries) { + const full = path.join(current, entry); + const rel = path.relative(base, full); + + let stat; + try { + stat = await statAsync(full); + } catch { + continue; + } + + if (stat.isDirectory()) { + await this.walkGlob(base, full, pattern, results); + } else { + // Simple glob: support * and ** + if (this.matchGlob(rel, pattern)) { + results.push(rel); + } + } + } + } + + private matchGlob(filePath: string, pattern: string): boolean { + const regexStr = pattern + .replace(/\./g, "\\.") + .replace(/\*\*/g, "DOUBLESTAR") + .replace(/\*/g, "[^/]*") + .replace(/DOUBLESTAR/g, ".*"); + const regex = new RegExp(`^${regexStr}$`); + return regex.test(filePath); + } + + private async grep( + params: Record, + workingDir: string, + start: number + ): Promise { + const searchPattern = String(params["pattern"] ?? ""); + const searchPath = resolveWithinRoot( + String(params["path"] ?? "."), + workingDir + ); + + if (!isWithinAllowedRoot(searchPath)) { + return { success: false, content: "", error: "Path outside allowed root", durationMs: Date.now() - start }; + } + + const results: string[] = []; + await this.grepDirectory(searchPath, searchPattern, results); + return { success: true, content: results.join("\n"), durationMs: Date.now() - start }; + } + + private async grepDirectory( + searchPath: string, + pattern: string, + results: string[] + ): Promise { + let stat; + try { + stat = await statAsync(searchPath); + } catch { + return; + } + + if (stat.isFile()) { + await this.grepFile(searchPath, pattern, results); + return; + } + + if (stat.isDirectory()) { + let entries: string[]; + try { + entries = await readdirAsync(searchPath); + } catch { + return; + } + for (const entry of entries) { + await this.grepDirectory(path.join(searchPath, entry), pattern, results); + } + } + } + + private async grepFile( + filePath: string, + pattern: string, + results: string[] + ): Promise { + let content: string; + try { + content = await readFileAsync(filePath, "utf8"); + } catch { + return; + } + + const regex = new RegExp(pattern, "gm"); + const lines = content.split("\n"); + lines.forEach((line, i) => { + if (regex.test(line)) { + results.push(`${filePath}:${i + 1}: ${line}`); + } + regex.lastIndex = 0; + }); + } + + private async listFiles( + params: Record, + workingDir: string, + start: number + ): Promise { + const dirPath = resolveWithinRoot( + String(params["path"] ?? "."), + workingDir + ); + + if (!isWithinAllowedRoot(dirPath)) { + return { success: false, content: "", error: "Path outside allowed root", durationMs: Date.now() - start }; + } + + const entries = await readdirAsync(dirPath); + const details: string[] = []; + + for (const entry of entries) { + const full = path.join(dirPath, entry); + try { + const stat = await statAsync(full); + const type = stat.isDirectory() ? "dir" : "file"; + details.push(`${type}\t${entry}`); + } catch { + details.push(`unknown\t${entry}`); + } + } + + return { success: true, content: details.join("\n"), durationMs: Date.now() - start }; + } +} diff --git a/packages/bridge/src/auth/rate_limiter.ts b/packages/bridge/src/auth/rate_limiter.ts new file mode 100644 index 0000000..8f61a7d --- /dev/null +++ b/packages/bridge/src/auth/rate_limiter.ts @@ -0,0 +1,49 @@ +import type { Request, Response, NextFunction } from "express"; + +interface RateLimitEntry { + count: number; + windowStart: number; +} + +const WINDOW_MS = 60 * 1000; // 1 minute +const MAX_REQUESTS = 60; + +const store = new Map(); + +function getClientIp(req: Request): string { + const forwarded = req.headers["x-forwarded-for"]; + if (typeof forwarded === "string") { + return forwarded.split(",")[0].trim(); + } + return req.socket.remoteAddress ?? "unknown"; +} + +export function rateLimiter( + req: Request, + res: Response, + next: NextFunction +): void { + const ip = getClientIp(req); + const now = Date.now(); + + const entry = store.get(ip); + + if (!entry || now - entry.windowStart >= WINDOW_MS) { + store.set(ip, { count: 1, windowStart: now }); + next(); + return; + } + + if (entry.count >= MAX_REQUESTS) { + const retryAfter = Math.ceil((WINDOW_MS - (now - entry.windowStart)) / 1000); + res.setHeader("Retry-After", retryAfter); + res.status(429).json({ + error: "Too Many Requests", + message: `Rate limit exceeded. Try again in ${retryAfter}s`, + }); + return; + } + + entry.count += 1; + next(); +} diff --git a/packages/bridge/src/auth/token_validator.ts b/packages/bridge/src/auth/token_validator.ts new file mode 100644 index 0000000..646b37b --- /dev/null +++ b/packages/bridge/src/auth/token_validator.ts @@ -0,0 +1,36 @@ +import type { Request, Response, NextFunction } from "express"; +import { config } from "../config"; + +function extractBearerToken(req: Request): string | null { + const auth = req.headers.authorization; + if (!auth || !auth.startsWith("Bearer ")) { + return null; + } + return auth.slice(7); +} + +export function validateBridgeToken( + req: Request, + res: Response, + next: NextFunction +): void { + const token = extractBearerToken(req); + if (!token || token !== config.BRIDGE_TOKEN) { + res.status(401).json({ error: "Unauthorized", message: "Invalid or missing bridge token" }); + return; + } + next(); +} + +export function validateHookToken( + req: Request, + res: Response, + next: NextFunction +): void { + const token = extractBearerToken(req); + if (!token || token !== config.HOOK_TOKEN) { + res.status(401).json({ error: "Unauthorized", message: "Invalid or missing hook token" }); + return; + } + next(); +} diff --git a/packages/bridge/src/config.ts b/packages/bridge/src/config.ts new file mode 100644 index 0000000..d07d58d --- /dev/null +++ b/packages/bridge/src/config.ts @@ -0,0 +1,30 @@ +import { z } from "zod"; + +const configSchema = z.object({ + PORT: z + .string() + .default("3000") + .transform((v) => parseInt(v, 10)), + BRIDGE_TOKEN: z.string().min(1, "BRIDGE_TOKEN is required"), + HOOK_TOKEN: z.string().min(1, "HOOK_TOKEN is required"), + ANTHROPIC_API_KEY: z.string().min(1, "ANTHROPIC_API_KEY is required"), + AGENT_MODEL: z.string().default("claude-opus-4-6"), + ALLOWED_PROJECT_ROOT: z + .string() + .min(1, "ALLOWED_PROJECT_ROOT is required"), +}); + +function loadConfig() { + const result = configSchema.safeParse(process.env); + if (!result.success) { + const messages = result.error.errors + .map((e) => ` ${e.path.join(".")}: ${e.message}`) + .join("\n"); + throw new Error(`Configuration error:\n${messages}`); + } + return result.data; +} + +export const config = loadConfig(); + +export type Config = typeof config; diff --git a/packages/bridge/src/files/file_service.ts b/packages/bridge/src/files/file_service.ts new file mode 100644 index 0000000..9d0027c --- /dev/null +++ b/packages/bridge/src/files/file_service.ts @@ -0,0 +1,127 @@ +import fs from "fs"; +import path from "path"; +import { promisify } from "util"; + +const readdirAsync = promisify(fs.readdir); +const statAsync = promisify(fs.stat); +const readFileAsync = promisify(fs.readFile); + +export interface FileEntry { + name: string; + type: "file" | "directory"; + size?: number; + modifiedAt?: string; +} + +export interface FileListResult { + entries: FileEntry[]; + total: number; + offset: number; + limit: number; + hasMore: boolean; +} + +export interface FileReadResult { + content: string; + totalLines: number; + offset: number; + limit: number; + hasMore: boolean; +} + +const DEFAULT_LIST_LIMIT = 100; +const DEFAULT_READ_LIMIT = 500; + +export class FileService { + constructor(private allowedRoot: string) {} + + async listDirectory( + dirPath: string, + options: { + offset?: number; + limit?: number; + includeHidden?: boolean; + } = {} + ): Promise { + const resolved = path.resolve(dirPath); + this.validatePath(resolved); + + const { offset = 0, limit = DEFAULT_LIST_LIMIT, includeHidden = false } = options; + + const names = await readdirAsync(resolved); + + const allEntries: FileEntry[] = []; + for (const name of names) { + if (!includeHidden && name.startsWith(".")) { + continue; + } + const full = path.join(resolved, name); + try { + const stat = await statAsync(full); + allEntries.push({ + name, + type: stat.isDirectory() ? "directory" : "file", + size: stat.isFile() ? stat.size : undefined, + modifiedAt: stat.mtime.toISOString(), + }); + } catch { + allEntries.push({ name, type: "file" }); + } + } + + // Sort: directories first, then files, both alphabetically + allEntries.sort((a, b) => { + if (a.type === b.type) { + return a.name.localeCompare(b.name); + } + return a.type === "directory" ? -1 : 1; + }); + + const total = allEntries.length; + const page = allEntries.slice(offset, offset + limit); + + return { + entries: page, + total, + offset, + limit, + hasMore: offset + limit < total, + }; + } + + async readFile( + filePath: string, + options: { + offset?: number; + limit?: number; + } = {} + ): Promise { + const resolved = path.resolve(filePath); + this.validatePath(resolved); + + const { offset = 0, limit = DEFAULT_READ_LIMIT } = options; + + const raw = await readFileAsync(resolved, "utf8"); + const allLines = raw.split("\n"); + const totalLines = allLines.length; + + const page = allLines.slice(offset, offset + limit); + + return { + content: page.join("\n"), + totalLines, + offset, + limit, + hasMore: offset + limit < totalLines, + }; + } + + private validatePath(p: string): void { + const resolvedRoot = path.resolve(this.allowedRoot); + if (!p.startsWith(resolvedRoot + path.sep) && p !== resolvedRoot) { + throw new Error( + `Access denied: path "${p}" is outside the allowed root "${resolvedRoot}"` + ); + } + } +} diff --git a/packages/bridge/src/git/diff_parser.ts b/packages/bridge/src/git/diff_parser.ts new file mode 100644 index 0000000..7ac075f --- /dev/null +++ b/packages/bridge/src/git/diff_parser.ts @@ -0,0 +1,152 @@ +import type { DiffFile, DiffHunk, DiffLine } from "../types"; + +const FILE_HEADER_RE = /^diff --git a\/(.*) b\/(.*)$/; +const OLD_FILE_RE = /^--- (?:a\/(.*)|\/(dev\/null))$/; +const NEW_FILE_RE = /^\+\+\+ (?:b\/(.*)|\/(dev\/null))$/; +const HUNK_HEADER_RE = /^@@ -(\d+)(?:,(\d+))? \+(\d+)(?:,(\d+))? @@(.*)$/; + +export function parseDiff(rawDiff: string): DiffFile[] { + const files: DiffFile[] = []; + if (!rawDiff || rawDiff.trim().length === 0) { + return files; + } + + const lines = rawDiff.split("\n"); + let i = 0; + + while (i < lines.length) { + const line = lines[i]; + + const fileHeaderMatch = FILE_HEADER_RE.exec(line); + if (!fileHeaderMatch) { + i++; + continue; + } + + const oldPathRaw = fileHeaderMatch[1]; + const newPathRaw = fileHeaderMatch[2]; + i++; + + let oldPath = oldPathRaw; + let newPath = newPathRaw; + let isNew = false; + let isDeleted = false; + let isRenamed = oldPath !== newPath; + + // Skip "index ..." lines + while (i < lines.length && lines[i].startsWith("index ")) { + i++; + } + + // Parse --- line + if (i < lines.length) { + const oldMatch = OLD_FILE_RE.exec(lines[i]); + if (oldMatch) { + if (lines[i] === "--- /dev/null") { + isNew = true; + } else if (oldMatch[1]) { + oldPath = oldMatch[1]; + } + i++; + } + } + + // Parse +++ line + if (i < lines.length) { + const newMatch = NEW_FILE_RE.exec(lines[i]); + if (newMatch) { + if (lines[i] === "+++ /dev/null") { + isDeleted = true; + } else if (newMatch[1]) { + newPath = newMatch[1]; + } + i++; + } + } + + const hunks: DiffHunk[] = []; + + // Parse hunks + while (i < lines.length) { + const hunkLine = lines[i]; + + // Stop if we hit the next file header + if (FILE_HEADER_RE.test(hunkLine)) { + break; + } + + const hunkMatch = HUNK_HEADER_RE.exec(hunkLine); + if (!hunkMatch) { + i++; + continue; + } + + const oldStart = parseInt(hunkMatch[1], 10); + const oldCount = hunkMatch[2] !== undefined ? parseInt(hunkMatch[2], 10) : 1; + const newStart = parseInt(hunkMatch[3], 10); + const newCount = hunkMatch[4] !== undefined ? parseInt(hunkMatch[4], 10) : 1; + const header = hunkLine; + i++; + + const diffLines: DiffLine[] = []; + let oldLineNum = oldStart; + let newLineNum = newStart; + + while (i < lines.length) { + const dl = lines[i]; + + if ( + FILE_HEADER_RE.test(dl) || + HUNK_HEADER_RE.test(dl) + ) { + break; + } + + if (dl.startsWith("+")) { + diffLines.push({ + type: "addition", + content: dl.slice(1), + new_line_number: newLineNum++, + }); + } else if (dl.startsWith("-")) { + diffLines.push({ + type: "deletion", + content: dl.slice(1), + old_line_number: oldLineNum++, + }); + } else if (dl.startsWith(" ") || dl === "") { + diffLines.push({ + type: "context", + content: dl.startsWith(" ") ? dl.slice(1) : dl, + old_line_number: oldLineNum++, + new_line_number: newLineNum++, + }); + } else if (dl.startsWith("\\")) { + // "\ No newline at end of file" — skip + } + + i++; + } + + hunks.push({ + old_start: oldStart, + old_count: oldCount, + new_start: newStart, + new_count: newCount, + header, + lines: diffLines, + }); + } + + files.push({ + old_path: oldPath, + new_path: newPath, + is_new: isNew, + is_deleted: isDeleted, + is_renamed: isRenamed, + hunks, + }); + } + + return files; +} diff --git a/packages/bridge/src/git/git_service.ts b/packages/bridge/src/git/git_service.ts new file mode 100644 index 0000000..4d05a6e --- /dev/null +++ b/packages/bridge/src/git/git_service.ts @@ -0,0 +1,116 @@ +import simpleGit, { type SimpleGit, type StatusResult } from "simple-git"; +import { parseDiff } from "./diff_parser"; +import type { + GitStatusPayload, + GitFileChange, + DiffFile, + GitBranch, +} from "../types"; + +function log(msg: string): void { + console.log(`[${new Date().toISOString()}] [GitService] ${msg}`); +} + +function mapStatusCode(code: string, staged: boolean): GitFileChange["status"] { + switch (code) { + case "A": + return "added"; + case "M": + return "modified"; + case "D": + return "deleted"; + case "R": + return "renamed"; + case "C": + return "copied"; + case "?": + return "untracked"; + default: + return "unknown"; + } +} + +export class GitService { + private git: SimpleGit; + private workingDirectory: string; + + constructor(workingDirectory: string) { + this.workingDirectory = workingDirectory; + this.git = simpleGit(workingDirectory); + } + + async getStatus(): Promise { + const status: StatusResult = await this.git.status(); + + const changes: GitFileChange[] = []; + + for (const f of status.files) { + const isStaged = f.index !== " " && f.index !== "?"; + changes.push({ + path: f.path, + status: mapStatusCode(isStaged ? f.index : f.working_dir, isStaged), + staged: isStaged, + }); + } + + return { + branch: status.current ?? "HEAD", + ahead: status.ahead, + behind: status.behind, + is_clean: status.isClean(), + changes, + }; + } + + async getDiff(files?: string[], cached?: boolean): Promise { + const args: string[] = []; + if (cached) args.push("--cached"); + if (files && files.length > 0) { + args.push("--"); + args.push(...files); + } + + const rawDiff = await this.git.diff(args); + return parseDiff(rawDiff); + } + + async commit(message: string, files?: string[]): Promise { + if (files && files.length > 0) { + await this.git.add(files); + } else { + await this.git.add("."); + } + await this.git.commit(message); + log(`Committed: ${message}`); + } + + async getBranches(): Promise { + const summary = await this.git.branch(["-a"]); + const branches: GitBranch[] = []; + + for (const [name, b] of Object.entries(summary.branches)) { + branches.push({ + name: b.name, + is_current: b.current, + is_remote: name.startsWith("remotes/"), + }); + } + + return branches; + } + + async checkout(branch: string): Promise { + await this.git.checkout(branch); + log(`Checked out: ${branch}`); + } + + async pull(): Promise { + await this.git.pull(); + log("Pulled latest changes"); + } + + async push(): Promise { + await this.git.push(); + log("Pushed changes"); + } +} diff --git a/packages/bridge/src/hooks/event_queue.ts b/packages/bridge/src/hooks/event_queue.ts new file mode 100644 index 0000000..eb43030 --- /dev/null +++ b/packages/bridge/src/hooks/event_queue.ts @@ -0,0 +1,37 @@ +import type { HookEvent } from "../types"; + +const MAX_QUEUE_SIZE = 1000; + +export class EventQueue { + private queue: HookEvent[] = []; + + enqueue(event: HookEvent): void { + if (this.queue.length >= MAX_QUEUE_SIZE) { + this.queue.shift(); // drop oldest + } + this.queue.push(event); + } + + dequeue(sessionId?: string): HookEvent[] { + if (!sessionId) { + const all = [...this.queue]; + this.queue = []; + return all; + } + const matching = this.queue.filter((e) => e.session_id === sessionId); + this.queue = this.queue.filter((e) => e.session_id !== sessionId); + return matching; + } + + clear(sessionId?: string): void { + if (!sessionId) { + this.queue = []; + } else { + this.queue = this.queue.filter((e) => e.session_id !== sessionId); + } + } + + size(): number { + return this.queue.length; + } +} diff --git a/packages/bridge/src/hooks/receiver.ts b/packages/bridge/src/hooks/receiver.ts new file mode 100644 index 0000000..9cca572 --- /dev/null +++ b/packages/bridge/src/hooks/receiver.ts @@ -0,0 +1,55 @@ +import { Router } from "express"; +import { v4 as uuidv4 } from "uuid"; +import { validateHookToken } from "../auth/token_validator"; +import { validateHookEvent } from "./validator"; +import { EventQueue } from "./event_queue"; +import { eventBus } from "../notifications/event_bus"; +import type { ConnectionManager } from "../websocket/connection_manager"; +import type { BridgeMessage, ClaudeEventPayload, HookEvent } from "../types"; + +function log(msg: string): void { + console.log(`[${new Date().toISOString()}] [HookReceiver] ${msg}`); +} + +export function createHooksRouter( + eventQueue: EventQueue, + connectionManager: ConnectionManager +): Router { + const router = Router(); + + router.post("/event", validateHookToken, (req, res) => { + const body: unknown = req.body; + + if (!validateHookEvent(body)) { + res.status(400).json({ error: "Bad Request", message: "Invalid hook event shape" }); + return; + } + + const event: HookEvent = body; + log(`Received event: ${event.event_type} (session=${event.session_id})`); + + eventQueue.enqueue(event); + + const claudeEventPayload: ClaudeEventPayload = { + event_type: event.event_type, + session_id: event.session_id, + timestamp: event.timestamp, + payload: event.payload, + }; + + eventBus.emitTyped("claude-event", claudeEventPayload); + + const msg: BridgeMessage = { + type: "claude_event", + id: uuidv4(), + timestamp: new Date().toISOString(), + payload: claudeEventPayload, + }; + + connectionManager.broadcast(msg); + + res.status(200).json({ received: true }); + }); + + return router; +} diff --git a/packages/bridge/src/hooks/validator.ts b/packages/bridge/src/hooks/validator.ts new file mode 100644 index 0000000..2aa849e --- /dev/null +++ b/packages/bridge/src/hooks/validator.ts @@ -0,0 +1,31 @@ +import type { HookEvent } from "../types"; + +export const VALID_EVENT_TYPES: string[] = [ + "PreToolUse", + "PostToolUse", + "Notification", + "Stop", + "SubagentStop", + "PreCompact", +]; + +export function validateHookEvent(event: unknown): event is HookEvent { + if (typeof event !== "object" || event === null) { + return false; + } + const e = event as Record; + + if (typeof e["event_type"] !== "string" || e["event_type"].length === 0) { + return false; + } + if (typeof e["session_id"] !== "string" || e["session_id"].length === 0) { + return false; + } + if (typeof e["timestamp"] !== "string" || e["timestamp"].length === 0) { + return false; + } + if (typeof e["payload"] !== "object" || e["payload"] === null) { + return false; + } + return true; +} diff --git a/packages/bridge/src/index.ts b/packages/bridge/src/index.ts new file mode 100644 index 0000000..9ee6421 --- /dev/null +++ b/packages/bridge/src/index.ts @@ -0,0 +1,7 @@ +import "dotenv/config"; +import { startServer } from "./server"; + +startServer().catch((err) => { + console.error(`[${new Date().toISOString()}] [Fatal] Failed to start server:`, err); + process.exit(1); +}); diff --git a/packages/bridge/src/notifications/dispatcher.ts b/packages/bridge/src/notifications/dispatcher.ts new file mode 100644 index 0000000..0a1674f --- /dev/null +++ b/packages/bridge/src/notifications/dispatcher.ts @@ -0,0 +1,59 @@ +import { v4 as uuidv4 } from "uuid"; +import { eventBus } from "./event_bus"; +import type { ConnectionManager } from "../websocket/connection_manager"; +import type { BridgeMessage, ClaudeEventPayload, StreamChunkPayload } from "../types"; + +function timestamp(): string { + return new Date().toISOString(); +} + +export class Dispatcher { + private connectionManager: ConnectionManager; + + constructor(connectionManager: ConnectionManager) { + this.connectionManager = connectionManager; + this.subscribe(); + } + + private subscribe(): void { + eventBus.onTyped("claude-event", (payload) => { + const msg: BridgeMessage = { + type: "claude_event", + id: uuidv4(), + timestamp: timestamp(), + payload: payload as ClaudeEventPayload, + }; + const sessionId = (payload as ClaudeEventPayload).session_id; + this.broadcast(msg, sessionId); + }); + + eventBus.onTyped("stream-chunk", (payload) => { + const chunk = payload as StreamChunkPayload; + const msg: BridgeMessage = { + type: "stream_chunk", + id: uuidv4(), + timestamp: timestamp(), + payload: chunk, + }; + const clients = this.connectionManager.getClientsForSession(chunk.session_id); + for (const client of clients) { + this.connectionManager.sendToClient(client.id, msg); + } + }); + } + + dispatch(clientId: string, message: BridgeMessage): void { + this.connectionManager.sendToClient(clientId, message); + } + + broadcast(message: BridgeMessage, sessionId?: string): void { + if (sessionId) { + const clients = this.connectionManager.getClientsForSession(sessionId); + for (const client of clients) { + this.connectionManager.sendToClient(client.id, message); + } + } else { + this.connectionManager.broadcast(message); + } + } +} diff --git a/packages/bridge/src/notifications/event_bus.ts b/packages/bridge/src/notifications/event_bus.ts new file mode 100644 index 0000000..457d67b --- /dev/null +++ b/packages/bridge/src/notifications/event_bus.ts @@ -0,0 +1,33 @@ +import { EventEmitter } from "events"; + +export type EventBusEvents = { + "claude-event": [payload: unknown]; + "session-event": [payload: unknown]; + "tool-event": [payload: unknown]; + "stream-chunk": [payload: unknown]; +}; + +class TypedEventBus extends EventEmitter { + emitTyped( + event: K, + ...args: EventBusEvents[K] + ): boolean { + return this.emit(event, ...args); + } + + onTyped( + event: K, + listener: (...args: EventBusEvents[K]) => void + ): this { + return this.on(event, listener as (...args: unknown[]) => void); + } + + offTyped( + event: K, + listener: (...args: EventBusEvents[K]) => void + ): this { + return this.off(event, listener as (...args: unknown[]) => void); + } +} + +export const eventBus = new TypedEventBus(); diff --git a/packages/bridge/src/server.ts b/packages/bridge/src/server.ts new file mode 100644 index 0000000..956c4b6 --- /dev/null +++ b/packages/bridge/src/server.ts @@ -0,0 +1,85 @@ +import http from "http"; +import express from "express"; +import cors from "cors"; +import { config } from "./config"; +import { ConnectionManager } from "./websocket/connection_manager"; +import { MessageHandler } from "./websocket/message_handler"; +import { WebSocketServer } from "./websocket/server"; +import { AgentSessionManager } from "./agents/session_manager"; +import { AgentSdkAdapter } from "./agents/agent_sdk_adapter"; +import { GitService } from "./git/git_service"; +import { EventQueue } from "./hooks/event_queue"; +import { createHooksRouter } from "./hooks/receiver"; +import { Dispatcher } from "./notifications/dispatcher"; +import { rateLimiter } from "./auth/rate_limiter"; + +function log(msg: string): void { + console.log(`[${new Date().toISOString()}] [Server] ${msg}`); +} + +export async function startServer(): Promise { + // Compose dependencies + const connectionManager = new ConnectionManager(); + const agentSessionManager = new AgentSessionManager(); + const agentSdkAdapter = new AgentSdkAdapter(agentSessionManager, connectionManager); + const gitService = new GitService(config.ALLOWED_PROJECT_ROOT); + const eventQueue = new EventQueue(); + + // Dispatcher subscribes to event bus and forwards to clients + const _dispatcher = new Dispatcher(connectionManager); + + const messageHandler = new MessageHandler( + connectionManager, + agentSdkAdapter, + agentSessionManager, + gitService + ); + + // Express app + const app = express(); + app.use(cors()); + app.use(express.json()); + app.use(rateLimiter); + + // Health check + app.get("/health", (_req, res) => { + res.json({ status: "ok", timestamp: new Date().toISOString() }); + }); + + // Hook receiver + const hooksRouter = createHooksRouter(eventQueue, connectionManager); + app.use("/hooks", hooksRouter); + + // HTTP server + const httpServer = http.createServer(app); + + // WebSocket server + const _wsServer = new WebSocketServer(httpServer, connectionManager, messageHandler); + + // Start listening + await new Promise((resolve) => { + httpServer.listen(config.PORT, () => { + log(`Bridge server listening on port ${config.PORT}`); + log(`Allowed project root: ${config.ALLOWED_PROJECT_ROOT}`); + resolve(); + }); + }); + + // Graceful shutdown + const shutdown = (signal: string) => { + log(`Received ${signal}, shutting down...`); + httpServer.close(() => { + log("HTTP server closed"); + process.exit(0); + }); + + // Force exit after 10s + setTimeout(() => { + log("Forced shutdown after timeout"); + process.exit(1); + }, 10_000).unref(); + }; + + process.on("SIGTERM", () => shutdown("SIGTERM")); + process.on("SIGINT", () => shutdown("SIGINT")); +} diff --git a/packages/bridge/src/terminal/output_stream.ts b/packages/bridge/src/terminal/output_stream.ts new file mode 100644 index 0000000..b9beabd --- /dev/null +++ b/packages/bridge/src/terminal/output_stream.ts @@ -0,0 +1,39 @@ +import { EventEmitter } from "events"; +import type { Readable } from "stream"; + +export class TerminalOutputStream extends EventEmitter { + private buffer: string[] = []; + private closed = false; + + constructor(readable?: Readable) { + super(); + if (readable) { + readable.on("data", (chunk: Buffer | string) => { + this.write(chunk.toString()); + }); + readable.on("end", () => { + this.close(); + }); + } + } + + write(data: string): void { + if (this.closed) return; + this.buffer.push(data); + this.emit("data", data); + } + + close(): void { + if (this.closed) return; + this.closed = true; + this.emit("close"); + } + + getBuffer(): string { + return this.buffer.join(""); + } + + isClosed(): boolean { + return this.closed; + } +} diff --git a/packages/bridge/src/terminal/terminal_manager.ts b/packages/bridge/src/terminal/terminal_manager.ts new file mode 100644 index 0000000..375e35a --- /dev/null +++ b/packages/bridge/src/terminal/terminal_manager.ts @@ -0,0 +1,102 @@ +import { spawn, type ChildProcess } from "child_process"; +import os from "os"; +import { v4 as uuidv4 } from "uuid"; +import { TerminalOutputStream } from "./output_stream"; +import { eventBus } from "../notifications/event_bus"; + +function log(msg: string): void { + console.log(`[${new Date().toISOString()}] [TerminalManager] ${msg}`); +} + +export interface TerminalSession { + id: string; + workingDirectory: string; + process: ChildProcess; + outputStream: TerminalOutputStream; + createdAt: string; +} + +export class TerminalManager { + private sessions = new Map(); + + createSession(id: string, workingDirectory: string): TerminalSession { + const shell = os.platform() === "win32" ? "cmd.exe" : "/bin/sh"; + const args = os.platform() === "win32" ? [] : []; + + const proc = spawn(shell, args, { + cwd: workingDirectory, + env: process.env, + stdio: ["pipe", "pipe", "pipe"], + }); + + const outputStream = new TerminalOutputStream(); + + proc.stdout?.on("data", (chunk: Buffer) => { + const data = chunk.toString(); + outputStream.write(data); + this.forwardOutput(id, data); + }); + + proc.stderr?.on("data", (chunk: Buffer) => { + const data = chunk.toString(); + outputStream.write(data); + this.forwardOutput(id, data); + }); + + proc.on("close", (code) => { + log(`Session ${id} exited with code ${code}`); + outputStream.close(); + eventBus.emitTyped("session-event", { + type: "terminal_exit", + session_id: id, + exit_code: code, + }); + }); + + const session: TerminalSession = { + id, + workingDirectory, + process: proc, + outputStream, + createdAt: new Date().toISOString(), + }; + + this.sessions.set(id, session); + log(`Created terminal session: ${id} (cwd=${workingDirectory})`); + return session; + } + + getSession(id: string): TerminalSession | undefined { + return this.sessions.get(id); + } + + closeSession(id: string): void { + const session = this.sessions.get(id); + if (!session) return; + try { + session.process.kill(); + } catch (_) { + // already dead + } + session.outputStream.close(); + this.sessions.delete(id); + log(`Closed terminal session: ${id}`); + } + + sendInput(id: string, data: string): void { + const session = this.sessions.get(id); + if (!session) { + log(`sendInput: session not found: ${id}`); + return; + } + session.process.stdin?.write(data); + } + + private forwardOutput(sessionId: string, data: string): void { + eventBus.emitTyped("tool-event", { + type: "terminal_output", + session_id: sessionId, + data, + }); + } +} diff --git a/packages/bridge/src/types.ts b/packages/bridge/src/types.ts new file mode 100644 index 0000000..672b909 --- /dev/null +++ b/packages/bridge/src/types.ts @@ -0,0 +1,322 @@ +import type WebSocket from "ws"; + +// --------------------------------------------------------------------------- +// Base envelope +// --------------------------------------------------------------------------- + +export interface BridgeMessage { + type: string; + id?: string; + timestamp: string; + payload: T; +} + +// --------------------------------------------------------------------------- +// Auth / connection +// --------------------------------------------------------------------------- + +export interface AuthPayload { + token: string; +} + +export interface ConnectionAckPayload { + client_id: string; + active_sessions: AgentSession[]; +} + +export interface ConnectionErrorPayload { + code: string; + message: string; +} + +// --------------------------------------------------------------------------- +// Heartbeat +// --------------------------------------------------------------------------- + +export type HeartbeatPingPayload = Record; +export type HeartbeatPongPayload = Record; + +// --------------------------------------------------------------------------- +// Sessions +// --------------------------------------------------------------------------- + +export interface SessionStartPayload { + session_id?: string; + working_directory?: string; + system_prompt?: string; + model?: string; +} + +export interface SessionReadyPayload { + session_id: string; + model: string; +} + +export interface SessionEndPayload { + session_id: string; +} + +// --------------------------------------------------------------------------- +// Chat / streaming +// --------------------------------------------------------------------------- + +export interface MessagePayload { + session_id: string; + content: string; + role?: "user" | "assistant"; +} + +export interface StreamStartPayload { + session_id: string; + message_id: string; +} + +export interface StreamChunkPayload { + session_id: string; + message_id: string; + delta: string; + index: number; +} + +export interface StreamEndPayload { + session_id: string; + message_id: string; + stop_reason: string; +} + +// --------------------------------------------------------------------------- +// Tools +// --------------------------------------------------------------------------- + +export interface ToolCallPayload { + session_id: string; + tool_call_id: string; + tool_name: string; + tool_input: Record; +} + +export interface ApprovalRequiredPayload { + session_id: string; + tool_call_id: string; + tool_name: string; + tool_input: Record; + message: string; +} + +export interface ApprovalResponsePayload { + session_id: string; + tool_call_id: string; + decision: "approve" | "reject"; + reason?: string; +} + +export interface ToolResultPayload { + session_id: string; + tool_call_id: string; + tool_name: string; + success: boolean; + content: string; + error?: string; + duration_ms: number; +} + +// --------------------------------------------------------------------------- +// Claude hook events +// --------------------------------------------------------------------------- + +export interface ClaudeEventPayload { + event_type: string; + session_id: string; + timestamp: string; + payload: Record; +} + +// --------------------------------------------------------------------------- +// Git +// --------------------------------------------------------------------------- + +export interface GitFileChange { + path: string; + status: + | "added" + | "modified" + | "deleted" + | "renamed" + | "copied" + | "untracked" + | "unknown"; + staged: boolean; +} + +export interface DiffLine { + type: "context" | "addition" | "deletion"; + content: string; + old_line_number?: number; + new_line_number?: number; +} + +export interface DiffHunk { + old_start: number; + old_count: number; + new_start: number; + new_count: number; + header: string; + lines: DiffLine[]; +} + +export interface DiffFile { + old_path: string; + new_path: string; + is_new: boolean; + is_deleted: boolean; + is_renamed: boolean; + hunks: DiffHunk[]; +} + +export interface GitStatusPayload { + branch: string; + ahead: number; + behind: number; + is_clean: boolean; + changes: GitFileChange[]; +} + +export interface GitStatusResponsePayload extends GitStatusPayload { + request_id?: string; +} + +export interface GitDiffPayload { + files?: string[]; + cached?: boolean; +} + +export interface GitDiffResponsePayload { + files: DiffFile[]; + request_id?: string; +} + +export interface GitCommitPayload { + message: string; + files?: string[]; +} + +export interface GitBranch { + name: string; + is_current: boolean; + is_remote: boolean; +} + +// --------------------------------------------------------------------------- +// Files +// --------------------------------------------------------------------------- + +export interface FileListPayload { + path: string; + offset?: number; + limit?: number; + includeHidden?: boolean; + request_id?: string; +} + +export interface FileEntry { + name: string; + path: string; + type: "file" | "directory"; + size?: number; + modified?: string; +} + +export interface FileListResponsePayload { + path: string; + entries: FileEntry[]; + total: number; + offset: number; + limit: number; + hasMore: boolean; + request_id?: string; +} + +export interface FileReadPayload { + path: string; + offset?: number; + limit?: number; + request_id?: string; +} + +export interface FileReadResponsePayload { + path: string; + content: string; + encoding: "utf8"; + totalLines: number; + offset: number; + limit: number; + hasMore: boolean; + request_id?: string; +} + +// --------------------------------------------------------------------------- +// Notifications +// --------------------------------------------------------------------------- + +export interface NotificationPayload { + notification_id: string; + title: string; + body: string; + level: "info" | "warning" | "error"; + session_id?: string; + metadata?: Record; +} + +export interface NotificationAckPayload { + notification_id: string; +} + +// --------------------------------------------------------------------------- +// Error +// --------------------------------------------------------------------------- + +export interface ErrorPayload { + code: string; + message: string; + request_type?: string; +} + +// --------------------------------------------------------------------------- +// Internal domain models +// --------------------------------------------------------------------------- + +export interface MobileClient { + id: string; + ws: WebSocket; + sessionIds: string[]; + authenticated: boolean; +} + +export interface AgentSession { + id: string; + model: string; + working_directory: string; + created_at: string; + status: "active" | "idle" | "closed"; +} + +export interface SessionConfig { + sessionId?: string; + workingDirectory?: string; + systemPrompt?: string; + model?: string; +} + +export interface HookEvent { + event_type: string; + session_id: string; + timestamp: string; + payload: Record; +} + +export interface ToolResult { + success: boolean; + content: string; + error?: string; + durationMs: number; +} diff --git a/packages/bridge/src/websocket/connection_manager.ts b/packages/bridge/src/websocket/connection_manager.ts new file mode 100644 index 0000000..8f52290 --- /dev/null +++ b/packages/bridge/src/websocket/connection_manager.ts @@ -0,0 +1,83 @@ +import type WebSocket from "ws"; +import type { MobileClient, BridgeMessage } from "../types"; + +function log(msg: string): void { + console.log(`[${new Date().toISOString()}] [ConnectionManager] ${msg}`); +} + +export class ConnectionManager { + private clients = new Map(); + + addClient(id: string, ws: WebSocket): void { + const client: MobileClient = { + id, + ws, + sessionIds: [], + authenticated: false, + }; + this.clients.set(id, client); + log(`Client added: ${id}`); + } + + authenticateClient(id: string): void { + const client = this.clients.get(id); + if (client) { + client.authenticated = true; + log(`Client authenticated: ${id}`); + } + } + + removeClient(id: string): void { + this.clients.delete(id); + log(`Client removed: ${id}`); + } + + getClient(id: string): MobileClient | undefined { + return this.clients.get(id); + } + + broadcast( + message: BridgeMessage, + filter?: (client: MobileClient) => boolean + ): void { + const json = JSON.stringify(message); + for (const client of this.clients.values()) { + if (!client.authenticated) continue; + if (filter && !filter(client)) continue; + this.sendRaw(client, json); + } + } + + sendToClient(id: string, message: BridgeMessage): void { + const client = this.clients.get(id); + if (!client) return; + this.sendRaw(client, JSON.stringify(message)); + } + + addSessionToClient(clientId: string, sessionId: string): void { + const client = this.clients.get(clientId); + if (client && !client.sessionIds.includes(sessionId)) { + client.sessionIds.push(sessionId); + } + } + + getClientsForSession(sessionId: string): MobileClient[] { + const result: MobileClient[] = []; + for (const client of this.clients.values()) { + if (client.authenticated && client.sessionIds.includes(sessionId)) { + result.push(client); + } + } + return result; + } + + private sendRaw(client: MobileClient, json: string): void { + try { + if (client.ws.readyState === 1 /* OPEN */) { + client.ws.send(json); + } + } catch (err) { + log(`Failed to send to client ${client.id}: ${String(err)}`); + } + } +} diff --git a/packages/bridge/src/websocket/message_handler.ts b/packages/bridge/src/websocket/message_handler.ts new file mode 100644 index 0000000..122ca6b --- /dev/null +++ b/packages/bridge/src/websocket/message_handler.ts @@ -0,0 +1,298 @@ +import path from "path"; +import { v4 as uuidv4 } from "uuid"; +import { config } from "../config"; +import type { ConnectionManager } from "./connection_manager"; +import type { AgentSdkAdapter } from "../agents/agent_sdk_adapter"; +import type { GitService } from "../git/git_service"; +import type { + BridgeMessage, + AuthPayload, + ConnectionAckPayload, + ConnectionErrorPayload, + SessionStartPayload, + MessagePayload, + ApprovalResponsePayload, + SessionEndPayload, + GitDiffPayload, + GitCommitPayload, + FileListPayload, + FileReadPayload, + ErrorPayload, + HeartbeatPongPayload, + FileListResponsePayload, + FileReadResponsePayload, +} from "../types"; +import type { AgentSessionManager } from "../agents/session_manager"; +import { FileService } from "../files/file_service"; + +function log(msg: string): void { + console.log(`[${new Date().toISOString()}] [MessageHandler] ${msg}`); +} + +function ts(): string { + return new Date().toISOString(); +} + +function errorMsg( + code: string, + message: string, + requestType?: string +): BridgeMessage { + return { + type: "error", + id: uuidv4(), + timestamp: ts(), + payload: { code, message, request_type: requestType }, + }; +} + +export class MessageHandler { + private fileService: FileService; + + constructor( + private connectionManager: ConnectionManager, + private agentSdkAdapter: AgentSdkAdapter, + private agentSessionManager: AgentSessionManager, + private gitService: GitService + ) { + this.fileService = new FileService(config.ALLOWED_PROJECT_ROOT); + } + + async handle(clientId: string, rawMessage: string): Promise { + let msg: BridgeMessage; + + try { + msg = JSON.parse(rawMessage) as BridgeMessage; + } catch { + this.connectionManager.sendToClient( + clientId, + errorMsg("PARSE_ERROR", "Invalid JSON message") + ); + return; + } + + const { type, payload } = msg; + + // Auth is allowed without authentication + if (type === "auth") { + await this.handleAuth(clientId, payload as AuthPayload); + return; + } + + // Heartbeat is allowed without authentication (but only if already authenticated in practice) + if (type === "heartbeat_ping") { + this.handleHeartbeat(clientId); + return; + } + + // All other messages require authentication + const client = this.connectionManager.getClient(clientId); + if (!client || !client.authenticated) { + this.connectionManager.sendToClient( + clientId, + { + type: "connection_error", + id: uuidv4(), + timestamp: ts(), + payload: { + code: "NOT_AUTHENTICATED", + message: "Client must authenticate before sending messages", + } as ConnectionErrorPayload, + } + ); + return; + } + + try { + switch (type) { + case "session_start": + await this.agentSdkAdapter.handleSessionStart(payload as SessionStartPayload, clientId); + break; + + case "message": + await this.agentSdkAdapter.handleMessage(payload as MessagePayload, clientId); + break; + + case "approval_response": + await this.agentSdkAdapter.handleApprovalResponse(payload as ApprovalResponsePayload, clientId); + break; + + case "session_end": + this.agentSdkAdapter.handleSessionEnd(payload as SessionEndPayload); + break; + + case "git_status_request": + await this.handleGitStatusRequest(clientId, msg.id); + break; + + case "git_commit": + await this.handleGitCommit(clientId, payload as GitCommitPayload); + break; + + case "git_diff": + await this.handleGitDiff(clientId, payload as GitDiffPayload, msg.id); + break; + + case "file_list": + await this.handleFileList(clientId, payload as FileListPayload); + break; + + case "file_read": + await this.handleFileRead(clientId, payload as FileReadPayload); + break; + + case "notification_ack": + // no-op in this implementation + break; + + default: + log(`Unknown message type: ${type} from client ${clientId}`); + this.connectionManager.sendToClient( + clientId, + errorMsg("UNKNOWN_TYPE", `Unknown message type: ${type}`, type) + ); + } + } catch (err) { + log(`Error handling ${type} for client ${clientId}: ${String(err)}`); + this.connectionManager.sendToClient( + clientId, + errorMsg("HANDLER_ERROR", String(err), type) + ); + } + } + + private async handleAuth(clientId: string, payload: AuthPayload): Promise { + if (!payload?.token || payload.token !== config.BRIDGE_TOKEN) { + this.connectionManager.sendToClient(clientId, { + type: "connection_error", + id: uuidv4(), + timestamp: ts(), + payload: { + code: "INVALID_TOKEN", + message: "Authentication failed: invalid token", + } as ConnectionErrorPayload, + }); + log(`Auth failed for client ${clientId}`); + return; + } + + this.connectionManager.authenticateClient(clientId); + + const activeSessions = this.agentSessionManager.getActiveSessions(); + + const ackMsg: BridgeMessage = { + type: "connection_ack", + id: uuidv4(), + timestamp: ts(), + payload: { + client_id: clientId, + active_sessions: activeSessions, + }, + }; + this.connectionManager.sendToClient(clientId, ackMsg); + log(`Auth succeeded for client ${clientId}`); + } + + private handleHeartbeat(clientId: string): void { + const pong: BridgeMessage = { + type: "heartbeat_pong", + id: uuidv4(), + timestamp: ts(), + payload: {}, + }; + this.connectionManager.sendToClient(clientId, pong); + } + + private async handleGitStatusRequest(clientId: string, requestId?: string): Promise { + const status = await this.gitService.getStatus(); + this.connectionManager.sendToClient(clientId, { + type: "git_status_response", + id: uuidv4(), + timestamp: ts(), + payload: { ...status, request_id: requestId }, + }); + } + + private async handleGitCommit(clientId: string, payload: GitCommitPayload): Promise { + await this.gitService.commit(payload.message, payload.files); + this.connectionManager.sendToClient(clientId, { + type: "git_status_response", + id: uuidv4(), + timestamp: ts(), + payload: { ...(await this.gitService.getStatus()) }, + }); + } + + private async handleGitDiff( + clientId: string, + payload: GitDiffPayload, + requestId?: string + ): Promise { + const files = await this.gitService.getDiff(payload.files, payload.cached); + this.connectionManager.sendToClient(clientId, { + type: "git_diff_response", + id: uuidv4(), + timestamp: ts(), + payload: { files, request_id: requestId }, + }); + } + + private async handleFileList(clientId: string, payload: FileListPayload): Promise { + const dirPath = path.resolve(payload.path); + const result = await this.fileService.listDirectory(dirPath, { + offset: payload.offset, + limit: payload.limit, + includeHidden: payload.includeHidden, + }); + + // Map FileService entries to the wire FileEntry shape (includes path) + const entries = result.entries.map((e) => ({ + name: e.name, + path: path.join(dirPath, e.name), + type: e.type, + size: e.size, + modified: e.modifiedAt, + })); + + const resp: BridgeMessage = { + type: "file_list_response", + id: uuidv4(), + timestamp: ts(), + payload: { + path: dirPath, + entries, + total: result.total, + offset: result.offset, + limit: result.limit, + hasMore: result.hasMore, + request_id: payload.request_id, + }, + }; + this.connectionManager.sendToClient(clientId, resp); + } + + private async handleFileRead(clientId: string, payload: FileReadPayload): Promise { + const filePath = path.resolve(payload.path); + const result = await this.fileService.readFile(filePath, { + offset: payload.offset, + limit: payload.limit, + }); + + const resp: BridgeMessage = { + type: "file_read_response", + id: uuidv4(), + timestamp: ts(), + payload: { + path: filePath, + content: result.content, + encoding: "utf8", + totalLines: result.totalLines, + offset: result.offset, + limit: result.limit, + hasMore: result.hasMore, + request_id: payload.request_id, + }, + }; + this.connectionManager.sendToClient(clientId, resp); + } +} diff --git a/packages/bridge/src/websocket/server.ts b/packages/bridge/src/websocket/server.ts new file mode 100644 index 0000000..32addd6 --- /dev/null +++ b/packages/bridge/src/websocket/server.ts @@ -0,0 +1,86 @@ +import { WebSocketServer as WsServer, type WebSocket } from "ws"; +import { v4 as uuidv4 } from "uuid"; +import type { IncomingMessage, Server } from "http"; +import type { ConnectionManager } from "./connection_manager"; +import type { MessageHandler } from "./message_handler"; + +const PING_INTERVAL_MS = 30_000; + +function log(msg: string): void { + console.log(`[${new Date().toISOString()}] [WebSocketServer] ${msg}`); +} + +export class WebSocketServer { + private wss: WsServer; + private pingInterval: NodeJS.Timeout | null = null; + + constructor( + httpServer: Server, + private connectionManager: ConnectionManager, + private messageHandler: MessageHandler + ) { + this.wss = new WsServer({ + server: httpServer, + perMessageDeflate: { + zlibDeflateOptions: { chunkSize: 1024, memLevel: 7, level: 3 }, + zlibInflateOptions: { chunkSize: 10 * 1024 }, + clientNoContextTakeover: true, + serverNoContextTakeover: true, + serverMaxWindowBits: 10, + concurrencyLimit: 10, + threshold: 1024, // only compress messages > 1KB + }, + }); + this.setup(); + } + + private setup(): void { + this.wss.on("connection", (ws: WebSocket, req: IncomingMessage) => { + const clientId = uuidv4(); + log(`New connection: ${clientId} from ${req.socket.remoteAddress}`); + + this.connectionManager.addClient(clientId, ws); + + ws.on("message", (data) => { + const raw = data.toString(); + this.messageHandler.handle(clientId, raw).catch((err) => { + log(`Unhandled error from client ${clientId}: ${String(err)}`); + }); + }); + + ws.on("close", (code, reason) => { + log(`Client disconnected: ${clientId} (code=${code}, reason=${reason.toString()})`); + this.connectionManager.removeClient(clientId); + }); + + ws.on("error", (err) => { + log(`WebSocket error for client ${clientId}: ${String(err)}`); + this.connectionManager.removeClient(clientId); + }); + }); + + this.wss.on("error", (err) => { + log(`WebSocketServer error: ${String(err)}`); + }); + + this.startPingInterval(); + } + + private startPingInterval(): void { + this.pingInterval = setInterval(() => { + this.wss.clients.forEach((ws) => { + if (ws.readyState === ws.OPEN) { + ws.ping(); + } + }); + }, PING_INTERVAL_MS); + } + + close(): void { + if (this.pingInterval) { + clearInterval(this.pingInterval); + this.pingInterval = null; + } + this.wss.close(); + } +} From 24a6b4e2067770ccf879874d6894f7d91979979a Mon Sep 17 00:00:00 2001 From: Fury3K Date: Wed, 18 Mar 2026 00:26:57 +0800 Subject: [PATCH 03/22] feat: add claude-code plugin for event forwarding --- packages/claude-plugin/README.md | 40 +++++++++++++ packages/claude-plugin/hooks.json | 93 +++++++++++++++++++++++++++++++ 2 files changed, 133 insertions(+) create mode 100644 packages/claude-plugin/README.md create mode 100644 packages/claude-plugin/hooks.json diff --git a/packages/claude-plugin/README.md b/packages/claude-plugin/README.md new file mode 100644 index 0000000..a9e9628 --- /dev/null +++ b/packages/claude-plugin/README.md @@ -0,0 +1,40 @@ +# ReCursor Claude Code Plugin + +Forwards Claude Code events to the ReCursor bridge server for mobile consumption. + +## Installation + +Copy this plugin to your Claude Code plugins directory: + +```bash +mkdir -p ~/.claude-code/plugins/recursor-bridge +cp hooks.json ~/.claude-code/plugins/recursor-bridge/hooks.json +``` + +## Configuration + +Set environment variables before running Claude Code: + +```bash +export RECURSOR_BRIDGE_URL=http://100.78.42.15:3000 # Your bridge server URL (Tailscale IP) +export RECURSOR_HOOK_TOKEN=your-hook-token-here # Matches HOOK_TOKEN in bridge .env +``` + +Or add them to your shell profile (`~/.zshrc`, `~/.bashrc`). + +## Events Forwarded + +- `SessionStart` — New Claude Code session begins +- `SessionEnd` — Session terminates +- `PreToolUse` — Agent about to use a tool +- `PostToolUse` — Tool execution completed +- `UserPromptSubmit` — User submits a prompt +- `Stop` — Agent stops execution +- `SubagentStop` — Subagent stops +- `Notification` — System notification + +## Security + +- Hook commands use `|| true` so failures do not block Claude Code operation +- The bridge validates the `RECURSOR_HOOK_TOKEN` before processing events +- Use HTTPS (`https://`) for the bridge URL in production (Tailscale provides encryption) diff --git a/packages/claude-plugin/hooks.json b/packages/claude-plugin/hooks.json new file mode 100644 index 0000000..b1d7bb4 --- /dev/null +++ b/packages/claude-plugin/hooks.json @@ -0,0 +1,93 @@ +{ + "description": "ReCursor bridge integration — forward Claude Code events to mobile app", + "hooks": { + "SessionStart": [ + { + "hooks": [ + { + "type": "command", + "command": "curl -s -X POST \"${RECURSOR_BRIDGE_URL:-http://localhost:3000}/hooks/event\" -H 'Content-Type: application/json' -H \"Authorization: Bearer ${RECURSOR_HOOK_TOKEN}\" -d @- || true", + "timeout": 10 + } + ] + } + ], + "SessionEnd": [ + { + "hooks": [ + { + "type": "command", + "command": "curl -s -X POST \"${RECURSOR_BRIDGE_URL:-http://localhost:3000}/hooks/event\" -H 'Content-Type: application/json' -H \"Authorization: Bearer ${RECURSOR_HOOK_TOKEN}\" -d @- || true", + "timeout": 10 + } + ] + } + ], + "PreToolUse": [ + { + "hooks": [ + { + "type": "command", + "command": "curl -s -X POST \"${RECURSOR_BRIDGE_URL:-http://localhost:3000}/hooks/event\" -H 'Content-Type: application/json' -H \"Authorization: Bearer ${RECURSOR_HOOK_TOKEN}\" -d @- || true", + "timeout": 10 + } + ] + } + ], + "PostToolUse": [ + { + "hooks": [ + { + "type": "command", + "command": "curl -s -X POST \"${RECURSOR_BRIDGE_URL:-http://localhost:3000}/hooks/event\" -H 'Content-Type: application/json' -H \"Authorization: Bearer ${RECURSOR_HOOK_TOKEN}\" -d @- || true", + "timeout": 10 + } + ] + } + ], + "UserPromptSubmit": [ + { + "hooks": [ + { + "type": "command", + "command": "curl -s -X POST \"${RECURSOR_BRIDGE_URL:-http://localhost:3000}/hooks/event\" -H 'Content-Type: application/json' -H \"Authorization: Bearer ${RECURSOR_HOOK_TOKEN}\" -d @- || true", + "timeout": 10 + } + ] + } + ], + "Stop": [ + { + "hooks": [ + { + "type": "command", + "command": "curl -s -X POST \"${RECURSOR_BRIDGE_URL:-http://localhost:3000}/hooks/event\" -H 'Content-Type: application/json' -H \"Authorization: Bearer ${RECURSOR_HOOK_TOKEN}\" -d @- || true", + "timeout": 10 + } + ] + } + ], + "Notification": [ + { + "hooks": [ + { + "type": "command", + "command": "curl -s -X POST \"${RECURSOR_BRIDGE_URL:-http://localhost:3000}/hooks/event\" -H 'Content-Type: application/json' -H \"Authorization: Bearer ${RECURSOR_HOOK_TOKEN}\" -d @- || true", + "timeout": 10 + } + ] + } + ], + "SubagentStop": [ + { + "hooks": [ + { + "type": "command", + "command": "curl -s -X POST \"${RECURSOR_BRIDGE_URL:-http://localhost:3000}/hooks/event\" -H 'Content-Type: application/json' -H \"Authorization: Bearer ${RECURSOR_HOOK_TOKEN}\" -d @- || true", + "timeout": 10 + } + ] + } + ] + } +} From 07ff1919034341f21351492a8a963d7e74d89e42 Mon Sep 17 00:00:00 2001 From: Fury3K Date: Wed, 18 Mar 2026 00:27:28 +0800 Subject: [PATCH 04/22] feat: implement initial recursor mobile application --- apps/mobile/.gitignore | 45 + apps/mobile/.metadata | 30 + apps/mobile/README.md | 17 + apps/mobile/android/.gitignore | 14 + apps/mobile/android/app/build.gradle.kts | 49 + .../android/app/src/debug/AndroidManifest.xml | 7 + .../android/app/src/main/AndroidManifest.xml | 45 + .../example/recursor_mobile/MainActivity.kt | 5 + .../res/drawable-v21/launch_background.xml | 12 + .../main/res/drawable/launch_background.xml | 12 + .../src/main/res/mipmap-hdpi/ic_launcher.png | Bin 0 -> 544 bytes .../src/main/res/mipmap-mdpi/ic_launcher.png | Bin 0 -> 442 bytes .../src/main/res/mipmap-xhdpi/ic_launcher.png | Bin 0 -> 721 bytes .../main/res/mipmap-xxhdpi/ic_launcher.png | Bin 0 -> 1031 bytes .../main/res/mipmap-xxxhdpi/ic_launcher.png | Bin 0 -> 1443 bytes .../app/src/main/res/values-night/styles.xml | 18 + .../app/src/main/res/values/styles.xml | 18 + .../app/src/profile/AndroidManifest.xml | 7 + apps/mobile/android/build.gradle.kts | 24 + apps/mobile/android/gradle.properties | 2 + .../gradle/wrapper/gradle-wrapper.properties | 5 + apps/mobile/android/settings.gradle.kts | 26 + .../assets/fonts/JetBrainsMono-Bold.ttf | Bin 0 -> 274096 bytes .../assets/fonts/JetBrainsMono-Regular.ttf | Bin 0 -> 270224 bytes apps/mobile/integration_test/app_test.dart | 36 + apps/mobile/integration_test/chat_test.dart | 19 + .../integration_test/patrol_test_config.dart | 2 + apps/mobile/lib/app.dart | 29 + apps/mobile/lib/core/auth/auth_provider.dart | 117 + .../mobile/lib/core/auth/auth_repository.dart | 49 + apps/mobile/lib/core/auth/auth_state.dart | 17 + .../lib/core/auth/auth_state.freezed.dart | 255 + apps/mobile/lib/core/auth/github_oauth.dart | 98 + apps/mobile/lib/core/auth/token_storage.dart | 29 + apps/mobile/lib/core/config/app_config.dart | 19 + .../lib/core/config/high_contrast_theme.dart | 56 + apps/mobile/lib/core/config/router.dart | 324 ++ apps/mobile/lib/core/config/theme.dart | 173 + apps/mobile/lib/core/models/agent_models.dart | 27 + .../lib/core/models/agent_models.freezed.dart | 367 ++ .../lib/core/models/agent_models.g.dart | 53 + apps/mobile/lib/core/models/file_models.dart | 22 + .../lib/core/models/file_models.freezed.dart | 306 ++ .../mobile/lib/core/models/file_models.g.dart | 38 + apps/mobile/lib/core/models/git_models.dart | 96 + .../lib/core/models/git_models.freezed.dart | 1527 ++++++ apps/mobile/lib/core/models/git_models.g.dart | 143 + apps/mobile/lib/core/models/hook_models.dart | 29 + .../lib/core/models/hook_models.freezed.dart | 237 + .../mobile/lib/core/models/hook_models.g.dart | 23 + .../lib/core/models/message_models.dart | 91 + .../core/models/message_models.freezed.dart | 1885 ++++++++ .../lib/core/models/message_models.g.dart | 176 + apps/mobile/lib/core/models/models.dart | 7 + .../lib/core/models/notification_models.dart | 26 + .../models/notification_models.freezed.dart | 344 ++ .../core/models/notification_models.g.dart | 50 + .../lib/core/models/session_models.dart | 52 + .../core/models/session_models.freezed.dart | 674 +++ .../lib/core/models/session_models.g.dart | 80 + .../core/monitoring/analytics_service.dart | 47 + .../lib/core/monitoring/sentry_service.dart | 56 + .../lib/core/network/bridge_socket.dart | 46 + .../lib/core/network/connection_state.dart | 50 + .../lib/core/network/websocket_messages.dart | 341 ++ .../lib/core/network/websocket_service.dart | 222 + .../notifications/notification_center.dart | 48 + .../notifications/notification_handler.dart | 94 + .../notifications/notification_service.dart | 82 + .../lib/core/providers/auth_provider.dart | 2 + .../lib/core/providers/bridge_provider.dart | 40 + .../lib/core/providers/database_provider.dart | 9 + .../core/providers/notification_provider.dart | 18 + .../core/providers/preferences_provider.dart | 3 + .../lib/core/providers/theme_provider.dart | 53 + .../core/providers/websocket_provider.dart | 21 + .../lib/core/storage/daos/message_dao.dart | 45 + .../lib/core/storage/daos/message_dao.g.dart | 9 + .../lib/core/storage/daos/session_dao.dart | 43 + .../lib/core/storage/daos/session_dao.g.dart | 8 + .../lib/core/storage/daos/sync_dao.dart | 50 + .../lib/core/storage/daos/sync_dao.g.dart | 8 + apps/mobile/lib/core/storage/database.dart | 40 + apps/mobile/lib/core/storage/database.g.dart | 4291 +++++++++++++++++ apps/mobile/lib/core/storage/preferences.dart | 77 + .../lib/core/storage/tables/agents_table.dart | 29 + .../core/storage/tables/approvals_table.dart | 36 + .../core/storage/tables/messages_table.dart | 29 + .../core/storage/tables/sessions_table.dart | 22 + .../core/storage/tables/sync_queue_table.dart | 19 + .../lib/core/sync/conflict_resolver.dart | 58 + apps/mobile/lib/core/sync/sync_queue.dart | 63 + apps/mobile/lib/core/sync/sync_service.dart | 48 + .../domain/providers/agent_provider.dart | 155 + .../screens/agent_config_screen.dart | 269 ++ .../screens/agent_list_screen.dart | 117 + .../presentation/widgets/agent_card.dart | 98 + .../domain/providers/approval_provider.dart | 199 + .../screens/approval_detail_screen.dart | 300 ++ .../screens/approvals_screen.dart | 181 + .../presentation/widgets/approval_card.dart | 156 + .../widgets/modification_editor.dart | 50 + .../screens/bridge_setup_screen.dart | 224 + .../presentation/screens/login_screen.dart | 151 + .../presentation/screens/splash_screen.dart | 65 + .../presentation/widgets/auth_button.dart | 73 + .../chat/domain/providers/chat_provider.dart | 262 + .../domain/providers/chat_provider.g.dart | 175 + .../domain/providers/session_provider.dart | 86 + .../domain/providers/session_provider.g.dart | 26 + .../presentation/screens/chat_screen.dart | 219 + .../screens/session_list_screen.dart | 193 + .../presentation/widgets/chat_input_bar.dart | 139 + .../presentation/widgets/message_bubble.dart | 112 + .../widgets/message_part_widget.dart | 114 + .../presentation/widgets/streaming_text.dart | 82 + .../chat/presentation/widgets/tool_card.dart | 299 ++ .../widgets/voice_input_sheet.dart | 195 + .../diff/domain/providers/diff_provider.dart | 45 + .../domain/providers/diff_provider.g.dart | 25 + .../screens/diff_viewer_screen.dart | 239 + .../presentation/widgets/diff_file_card.dart | 105 + .../presentation/widgets/diff_hunk_view.dart | 41 + .../widgets/diff_line_widget.dart | 97 + .../presentation/widgets/diff_viewer.dart | 28 + .../git/domain/providers/git_provider.dart | 101 + .../presentation/screens/commit_screen.dart | 131 + .../git/presentation/screens/git_screen.dart | 185 + .../widgets/file_change_tile.dart | 93 + .../presentation/widgets/git_status_card.dart | 80 + apps/mobile/lib/features/home/home_shell.dart | 122 + .../repos/domain/providers/repo_provider.dart | 239 + .../screens/file_tree_screen.dart | 152 + .../screens/file_viewer_screen.dart | 172 + .../presentation/widgets/breadcrumb_nav.dart | 125 + .../widgets/file_tree_node_widget.dart | 133 + .../widgets/syntax_highlighted_file.dart | 387 ++ .../providers/session_timeline_provider.dart | 59 + .../screens/session_detail_screen.dart | 148 + .../presentation/widgets/session_card.dart | 136 + .../widgets/session_timeline.dart | 35 + .../presentation/widgets/timeline_tile.dart | 142 + .../presentation/screens/settings_screen.dart | 201 + .../presentation/widgets/setting_tile.dart | 42 + .../domain/providers/terminal_provider.dart | 91 + .../presentation/screens/terminal_screen.dart | 329 ++ .../presentation/widgets/ansi_renderer.dart | 32 + .../presentation/widgets/terminal_output.dart | 26 + apps/mobile/lib/main.dart | 30 + apps/mobile/lib/shared/constants/colors.dart | 34 + apps/mobile/lib/shared/constants/dimens.dart | 22 + .../lib/shared/constants/typography.dart | 29 + apps/mobile/lib/shared/utils/ansi_parser.dart | 112 + .../lib/shared/utils/date_formatter.dart | 55 + apps/mobile/lib/shared/utils/diff_parser.dart | 158 + .../mobile/lib/shared/widgets/code_block.dart | 109 + .../shared/widgets/connection_status_bar.dart | 45 + .../lib/shared/widgets/empty_state.dart | 59 + .../mobile/lib/shared/widgets/error_card.dart | 55 + .../lib/shared/widgets/expandable_card.dart | 96 + .../lib/shared/widgets/loading_indicator.dart | 30 + .../lib/shared/widgets/markdown_view.dart | 47 + .../mobile/lib/shared/widgets/risk_badge.dart | 38 + apps/mobile/lib/shared/widgets/tool_icon.dart | 35 + apps/mobile/pubspec.lock | 998 +++- apps/mobile/pubspec.yaml | 70 +- apps/mobile/test/widget_test.dart | 30 + fastlane/Appfile | 10 + fastlane/Fastfile | 81 + fastlane/Matchfile | 4 + fastlane/Pluginfile | 5 + fastlane/metadata/en-US/description.txt | 20 + fastlane/metadata/en-US/keywords.txt | 1 + fastlane/metadata/en-US/name.txt | 1 + fastlane/metadata/en-US/privacy_url.txt | 1 + fastlane/metadata/en-US/release_notes.txt | 10 + fastlane/metadata/en-US/subtitle.txt | 1 + fastlane/metadata/en-US/support_url.txt | 1 + 178 files changed, 23672 insertions(+), 15 deletions(-) create mode 100644 apps/mobile/.gitignore create mode 100644 apps/mobile/.metadata create mode 100644 apps/mobile/README.md create mode 100644 apps/mobile/android/.gitignore create mode 100644 apps/mobile/android/app/build.gradle.kts create mode 100644 apps/mobile/android/app/src/debug/AndroidManifest.xml create mode 100644 apps/mobile/android/app/src/main/AndroidManifest.xml create mode 100644 apps/mobile/android/app/src/main/kotlin/com/example/recursor_mobile/MainActivity.kt create mode 100644 apps/mobile/android/app/src/main/res/drawable-v21/launch_background.xml create mode 100644 apps/mobile/android/app/src/main/res/drawable/launch_background.xml create mode 100644 apps/mobile/android/app/src/main/res/mipmap-hdpi/ic_launcher.png create mode 100644 apps/mobile/android/app/src/main/res/mipmap-mdpi/ic_launcher.png create mode 100644 apps/mobile/android/app/src/main/res/mipmap-xhdpi/ic_launcher.png create mode 100644 apps/mobile/android/app/src/main/res/mipmap-xxhdpi/ic_launcher.png create mode 100644 apps/mobile/android/app/src/main/res/mipmap-xxxhdpi/ic_launcher.png create mode 100644 apps/mobile/android/app/src/main/res/values-night/styles.xml create mode 100644 apps/mobile/android/app/src/main/res/values/styles.xml create mode 100644 apps/mobile/android/app/src/profile/AndroidManifest.xml create mode 100644 apps/mobile/android/build.gradle.kts create mode 100644 apps/mobile/android/gradle.properties create mode 100644 apps/mobile/android/gradle/wrapper/gradle-wrapper.properties create mode 100644 apps/mobile/android/settings.gradle.kts create mode 100644 apps/mobile/assets/fonts/JetBrainsMono-Bold.ttf create mode 100644 apps/mobile/assets/fonts/JetBrainsMono-Regular.ttf create mode 100644 apps/mobile/integration_test/app_test.dart create mode 100644 apps/mobile/integration_test/chat_test.dart create mode 100644 apps/mobile/integration_test/patrol_test_config.dart create mode 100644 apps/mobile/lib/app.dart create mode 100644 apps/mobile/lib/core/auth/auth_provider.dart create mode 100644 apps/mobile/lib/core/auth/auth_repository.dart create mode 100644 apps/mobile/lib/core/auth/auth_state.dart create mode 100644 apps/mobile/lib/core/auth/auth_state.freezed.dart create mode 100644 apps/mobile/lib/core/auth/github_oauth.dart create mode 100644 apps/mobile/lib/core/auth/token_storage.dart create mode 100644 apps/mobile/lib/core/config/app_config.dart create mode 100644 apps/mobile/lib/core/config/high_contrast_theme.dart create mode 100644 apps/mobile/lib/core/config/router.dart create mode 100644 apps/mobile/lib/core/config/theme.dart create mode 100644 apps/mobile/lib/core/models/agent_models.dart create mode 100644 apps/mobile/lib/core/models/agent_models.freezed.dart create mode 100644 apps/mobile/lib/core/models/agent_models.g.dart create mode 100644 apps/mobile/lib/core/models/file_models.dart create mode 100644 apps/mobile/lib/core/models/file_models.freezed.dart create mode 100644 apps/mobile/lib/core/models/file_models.g.dart create mode 100644 apps/mobile/lib/core/models/git_models.dart create mode 100644 apps/mobile/lib/core/models/git_models.freezed.dart create mode 100644 apps/mobile/lib/core/models/git_models.g.dart create mode 100644 apps/mobile/lib/core/models/hook_models.dart create mode 100644 apps/mobile/lib/core/models/hook_models.freezed.dart create mode 100644 apps/mobile/lib/core/models/hook_models.g.dart create mode 100644 apps/mobile/lib/core/models/message_models.dart create mode 100644 apps/mobile/lib/core/models/message_models.freezed.dart create mode 100644 apps/mobile/lib/core/models/message_models.g.dart create mode 100644 apps/mobile/lib/core/models/models.dart create mode 100644 apps/mobile/lib/core/models/notification_models.dart create mode 100644 apps/mobile/lib/core/models/notification_models.freezed.dart create mode 100644 apps/mobile/lib/core/models/notification_models.g.dart create mode 100644 apps/mobile/lib/core/models/session_models.dart create mode 100644 apps/mobile/lib/core/models/session_models.freezed.dart create mode 100644 apps/mobile/lib/core/models/session_models.g.dart create mode 100644 apps/mobile/lib/core/monitoring/analytics_service.dart create mode 100644 apps/mobile/lib/core/monitoring/sentry_service.dart create mode 100644 apps/mobile/lib/core/network/bridge_socket.dart create mode 100644 apps/mobile/lib/core/network/connection_state.dart create mode 100644 apps/mobile/lib/core/network/websocket_messages.dart create mode 100644 apps/mobile/lib/core/network/websocket_service.dart create mode 100644 apps/mobile/lib/core/notifications/notification_center.dart create mode 100644 apps/mobile/lib/core/notifications/notification_handler.dart create mode 100644 apps/mobile/lib/core/notifications/notification_service.dart create mode 100644 apps/mobile/lib/core/providers/auth_provider.dart create mode 100644 apps/mobile/lib/core/providers/bridge_provider.dart create mode 100644 apps/mobile/lib/core/providers/database_provider.dart create mode 100644 apps/mobile/lib/core/providers/notification_provider.dart create mode 100644 apps/mobile/lib/core/providers/preferences_provider.dart create mode 100644 apps/mobile/lib/core/providers/theme_provider.dart create mode 100644 apps/mobile/lib/core/providers/websocket_provider.dart create mode 100644 apps/mobile/lib/core/storage/daos/message_dao.dart create mode 100644 apps/mobile/lib/core/storage/daos/message_dao.g.dart create mode 100644 apps/mobile/lib/core/storage/daos/session_dao.dart create mode 100644 apps/mobile/lib/core/storage/daos/session_dao.g.dart create mode 100644 apps/mobile/lib/core/storage/daos/sync_dao.dart create mode 100644 apps/mobile/lib/core/storage/daos/sync_dao.g.dart create mode 100644 apps/mobile/lib/core/storage/database.dart create mode 100644 apps/mobile/lib/core/storage/database.g.dart create mode 100644 apps/mobile/lib/core/storage/preferences.dart create mode 100644 apps/mobile/lib/core/storage/tables/agents_table.dart create mode 100644 apps/mobile/lib/core/storage/tables/approvals_table.dart create mode 100644 apps/mobile/lib/core/storage/tables/messages_table.dart create mode 100644 apps/mobile/lib/core/storage/tables/sessions_table.dart create mode 100644 apps/mobile/lib/core/storage/tables/sync_queue_table.dart create mode 100644 apps/mobile/lib/core/sync/conflict_resolver.dart create mode 100644 apps/mobile/lib/core/sync/sync_queue.dart create mode 100644 apps/mobile/lib/core/sync/sync_service.dart create mode 100644 apps/mobile/lib/features/agents/domain/providers/agent_provider.dart create mode 100644 apps/mobile/lib/features/agents/presentation/screens/agent_config_screen.dart create mode 100644 apps/mobile/lib/features/agents/presentation/screens/agent_list_screen.dart create mode 100644 apps/mobile/lib/features/agents/presentation/widgets/agent_card.dart create mode 100644 apps/mobile/lib/features/approvals/domain/providers/approval_provider.dart create mode 100644 apps/mobile/lib/features/approvals/presentation/screens/approval_detail_screen.dart create mode 100644 apps/mobile/lib/features/approvals/presentation/screens/approvals_screen.dart create mode 100644 apps/mobile/lib/features/approvals/presentation/widgets/approval_card.dart create mode 100644 apps/mobile/lib/features/approvals/presentation/widgets/modification_editor.dart create mode 100644 apps/mobile/lib/features/auth/presentation/screens/bridge_setup_screen.dart create mode 100644 apps/mobile/lib/features/auth/presentation/screens/login_screen.dart create mode 100644 apps/mobile/lib/features/auth/presentation/screens/splash_screen.dart create mode 100644 apps/mobile/lib/features/auth/presentation/widgets/auth_button.dart create mode 100644 apps/mobile/lib/features/chat/domain/providers/chat_provider.dart create mode 100644 apps/mobile/lib/features/chat/domain/providers/chat_provider.g.dart create mode 100644 apps/mobile/lib/features/chat/domain/providers/session_provider.dart create mode 100644 apps/mobile/lib/features/chat/domain/providers/session_provider.g.dart create mode 100644 apps/mobile/lib/features/chat/presentation/screens/chat_screen.dart create mode 100644 apps/mobile/lib/features/chat/presentation/screens/session_list_screen.dart create mode 100644 apps/mobile/lib/features/chat/presentation/widgets/chat_input_bar.dart create mode 100644 apps/mobile/lib/features/chat/presentation/widgets/message_bubble.dart create mode 100644 apps/mobile/lib/features/chat/presentation/widgets/message_part_widget.dart create mode 100644 apps/mobile/lib/features/chat/presentation/widgets/streaming_text.dart create mode 100644 apps/mobile/lib/features/chat/presentation/widgets/tool_card.dart create mode 100644 apps/mobile/lib/features/chat/presentation/widgets/voice_input_sheet.dart create mode 100644 apps/mobile/lib/features/diff/domain/providers/diff_provider.dart create mode 100644 apps/mobile/lib/features/diff/domain/providers/diff_provider.g.dart create mode 100644 apps/mobile/lib/features/diff/presentation/screens/diff_viewer_screen.dart create mode 100644 apps/mobile/lib/features/diff/presentation/widgets/diff_file_card.dart create mode 100644 apps/mobile/lib/features/diff/presentation/widgets/diff_hunk_view.dart create mode 100644 apps/mobile/lib/features/diff/presentation/widgets/diff_line_widget.dart create mode 100644 apps/mobile/lib/features/diff/presentation/widgets/diff_viewer.dart create mode 100644 apps/mobile/lib/features/git/domain/providers/git_provider.dart create mode 100644 apps/mobile/lib/features/git/presentation/screens/commit_screen.dart create mode 100644 apps/mobile/lib/features/git/presentation/screens/git_screen.dart create mode 100644 apps/mobile/lib/features/git/presentation/widgets/file_change_tile.dart create mode 100644 apps/mobile/lib/features/git/presentation/widgets/git_status_card.dart create mode 100644 apps/mobile/lib/features/home/home_shell.dart create mode 100644 apps/mobile/lib/features/repos/domain/providers/repo_provider.dart create mode 100644 apps/mobile/lib/features/repos/presentation/screens/file_tree_screen.dart create mode 100644 apps/mobile/lib/features/repos/presentation/screens/file_viewer_screen.dart create mode 100644 apps/mobile/lib/features/repos/presentation/widgets/breadcrumb_nav.dart create mode 100644 apps/mobile/lib/features/repos/presentation/widgets/file_tree_node_widget.dart create mode 100644 apps/mobile/lib/features/repos/presentation/widgets/syntax_highlighted_file.dart create mode 100644 apps/mobile/lib/features/session/domain/providers/session_timeline_provider.dart create mode 100644 apps/mobile/lib/features/session/presentation/screens/session_detail_screen.dart create mode 100644 apps/mobile/lib/features/session/presentation/widgets/session_card.dart create mode 100644 apps/mobile/lib/features/session/presentation/widgets/session_timeline.dart create mode 100644 apps/mobile/lib/features/session/presentation/widgets/timeline_tile.dart create mode 100644 apps/mobile/lib/features/settings/presentation/screens/settings_screen.dart create mode 100644 apps/mobile/lib/features/settings/presentation/widgets/setting_tile.dart create mode 100644 apps/mobile/lib/features/terminal/domain/providers/terminal_provider.dart create mode 100644 apps/mobile/lib/features/terminal/presentation/screens/terminal_screen.dart create mode 100644 apps/mobile/lib/features/terminal/presentation/widgets/ansi_renderer.dart create mode 100644 apps/mobile/lib/features/terminal/presentation/widgets/terminal_output.dart create mode 100644 apps/mobile/lib/main.dart create mode 100644 apps/mobile/lib/shared/constants/colors.dart create mode 100644 apps/mobile/lib/shared/constants/dimens.dart create mode 100644 apps/mobile/lib/shared/constants/typography.dart create mode 100644 apps/mobile/lib/shared/utils/ansi_parser.dart create mode 100644 apps/mobile/lib/shared/utils/date_formatter.dart create mode 100644 apps/mobile/lib/shared/utils/diff_parser.dart create mode 100644 apps/mobile/lib/shared/widgets/code_block.dart create mode 100644 apps/mobile/lib/shared/widgets/connection_status_bar.dart create mode 100644 apps/mobile/lib/shared/widgets/empty_state.dart create mode 100644 apps/mobile/lib/shared/widgets/error_card.dart create mode 100644 apps/mobile/lib/shared/widgets/expandable_card.dart create mode 100644 apps/mobile/lib/shared/widgets/loading_indicator.dart create mode 100644 apps/mobile/lib/shared/widgets/markdown_view.dart create mode 100644 apps/mobile/lib/shared/widgets/risk_badge.dart create mode 100644 apps/mobile/lib/shared/widgets/tool_icon.dart create mode 100644 apps/mobile/test/widget_test.dart create mode 100644 fastlane/Appfile create mode 100644 fastlane/Fastfile create mode 100644 fastlane/Matchfile create mode 100644 fastlane/Pluginfile create mode 100644 fastlane/metadata/en-US/description.txt create mode 100644 fastlane/metadata/en-US/keywords.txt create mode 100644 fastlane/metadata/en-US/name.txt create mode 100644 fastlane/metadata/en-US/privacy_url.txt create mode 100644 fastlane/metadata/en-US/release_notes.txt create mode 100644 fastlane/metadata/en-US/subtitle.txt create mode 100644 fastlane/metadata/en-US/support_url.txt diff --git a/apps/mobile/.gitignore b/apps/mobile/.gitignore new file mode 100644 index 0000000..3820a95 --- /dev/null +++ b/apps/mobile/.gitignore @@ -0,0 +1,45 @@ +# Miscellaneous +*.class +*.log +*.pyc +*.swp +.DS_Store +.atom/ +.build/ +.buildlog/ +.history +.svn/ +.swiftpm/ +migrate_working_dir/ + +# IntelliJ related +*.iml +*.ipr +*.iws +.idea/ + +# The .vscode folder contains launch configuration and tasks you configure in +# VS Code which you may wish to be included in version control, so this line +# is commented out by default. +#.vscode/ + +# Flutter/Dart/Pub related +**/doc/api/ +**/ios/Flutter/.last_build_id +.dart_tool/ +.flutter-plugins-dependencies +.pub-cache/ +.pub/ +/build/ +/coverage/ + +# Symbolication related +app.*.symbols + +# Obfuscation related +app.*.map.json + +# Android Studio will place build artifacts here +/android/app/debug +/android/app/profile +/android/app/release diff --git a/apps/mobile/.metadata b/apps/mobile/.metadata new file mode 100644 index 0000000..df13aa7 --- /dev/null +++ b/apps/mobile/.metadata @@ -0,0 +1,30 @@ +# This file tracks properties of this Flutter project. +# Used by Flutter tool to assess capabilities and perform upgrades etc. +# +# This file should be version controlled and should not be manually edited. + +version: + revision: "ff37bef603469fb030f2b72995ab929ccfc227f0" + channel: "stable" + +project_type: app + +# Tracks metadata for the flutter migrate command +migration: + platforms: + - platform: root + create_revision: ff37bef603469fb030f2b72995ab929ccfc227f0 + base_revision: ff37bef603469fb030f2b72995ab929ccfc227f0 + - platform: android + create_revision: ff37bef603469fb030f2b72995ab929ccfc227f0 + base_revision: ff37bef603469fb030f2b72995ab929ccfc227f0 + + # User provided section + + # List of Local paths (relative to this file) that should be + # ignored by the migrate tool. + # + # Files that are not part of the templates will be ignored by default. + unmanaged_files: + - 'lib/main.dart' + - 'ios/Runner.xcodeproj/project.pbxproj' diff --git a/apps/mobile/README.md b/apps/mobile/README.md new file mode 100644 index 0000000..6ac17cf --- /dev/null +++ b/apps/mobile/README.md @@ -0,0 +1,17 @@ +# recursor_mobile + +A new Flutter project. + +## Getting Started + +This project is a starting point for a Flutter application. + +A few resources to get you started if this is your first Flutter project: + +- [Learn Flutter](https://docs.flutter.dev/get-started/learn-flutter) +- [Write your first Flutter app](https://docs.flutter.dev/get-started/codelab) +- [Flutter learning resources](https://docs.flutter.dev/reference/learning-resources) + +For help getting started with Flutter development, view the +[online documentation](https://docs.flutter.dev/), which offers tutorials, +samples, guidance on mobile development, and a full API reference. diff --git a/apps/mobile/android/.gitignore b/apps/mobile/android/.gitignore new file mode 100644 index 0000000..be3943c --- /dev/null +++ b/apps/mobile/android/.gitignore @@ -0,0 +1,14 @@ +gradle-wrapper.jar +/.gradle +/captures/ +/gradlew +/gradlew.bat +/local.properties +GeneratedPluginRegistrant.java +.cxx/ + +# Remember to never publicly share your keystore. +# See https://flutter.dev/to/reference-keystore +key.properties +**/*.keystore +**/*.jks diff --git a/apps/mobile/android/app/build.gradle.kts b/apps/mobile/android/app/build.gradle.kts new file mode 100644 index 0000000..9781900 --- /dev/null +++ b/apps/mobile/android/app/build.gradle.kts @@ -0,0 +1,49 @@ +plugins { + id("com.android.application") + id("kotlin-android") + // The Flutter Gradle Plugin must be applied after the Android and Kotlin Gradle plugins. + id("dev.flutter.flutter-gradle-plugin") +} + +android { + namespace = "com.example.recursor_mobile" + compileSdk = flutter.compileSdkVersion + ndkVersion = flutter.ndkVersion + + compileOptions { + sourceCompatibility = JavaVersion.VERSION_17 + targetCompatibility = JavaVersion.VERSION_17 + isCoreLibraryDesugaringEnabled = true + } + + kotlinOptions { + jvmTarget = JavaVersion.VERSION_17.toString() + } + + defaultConfig { + // TODO: Specify your own unique Application ID (https://developer.android.com/studio/build/application-id.html). + applicationId = "com.example.recursor_mobile" + // You can update the following values to match your application needs. + // For more information, see: https://flutter.dev/to/review-gradle-config. + minSdk = flutter.minSdkVersion + targetSdk = flutter.targetSdkVersion + versionCode = flutter.versionCode + versionName = flutter.versionName + } + + buildTypes { + release { + // TODO: Add your own signing config for the release build. + // Signing with the debug keys for now, so `flutter run --release` works. + signingConfig = signingConfigs.getByName("debug") + } + } +} + +flutter { + source = "../.." +} + +dependencies { + coreLibraryDesugaring("com.android.tools:desugar_jdk_libs:2.1.4") +} diff --git a/apps/mobile/android/app/src/debug/AndroidManifest.xml b/apps/mobile/android/app/src/debug/AndroidManifest.xml new file mode 100644 index 0000000..399f698 --- /dev/null +++ b/apps/mobile/android/app/src/debug/AndroidManifest.xml @@ -0,0 +1,7 @@ + + + + diff --git a/apps/mobile/android/app/src/main/AndroidManifest.xml b/apps/mobile/android/app/src/main/AndroidManifest.xml new file mode 100644 index 0000000..2612599 --- /dev/null +++ b/apps/mobile/android/app/src/main/AndroidManifest.xml @@ -0,0 +1,45 @@ + + + + + + + + + + + + + + + + + + + + + diff --git a/apps/mobile/android/app/src/main/kotlin/com/example/recursor_mobile/MainActivity.kt b/apps/mobile/android/app/src/main/kotlin/com/example/recursor_mobile/MainActivity.kt new file mode 100644 index 0000000..b9aa7f6 --- /dev/null +++ b/apps/mobile/android/app/src/main/kotlin/com/example/recursor_mobile/MainActivity.kt @@ -0,0 +1,5 @@ +package com.example.recursor_mobile + +import io.flutter.embedding.android.FlutterActivity + +class MainActivity : FlutterActivity() diff --git a/apps/mobile/android/app/src/main/res/drawable-v21/launch_background.xml b/apps/mobile/android/app/src/main/res/drawable-v21/launch_background.xml new file mode 100644 index 0000000..f74085f --- /dev/null +++ b/apps/mobile/android/app/src/main/res/drawable-v21/launch_background.xml @@ -0,0 +1,12 @@ + + + + + + + + diff --git a/apps/mobile/android/app/src/main/res/drawable/launch_background.xml b/apps/mobile/android/app/src/main/res/drawable/launch_background.xml new file mode 100644 index 0000000..304732f --- /dev/null +++ b/apps/mobile/android/app/src/main/res/drawable/launch_background.xml @@ -0,0 +1,12 @@ + + + + + + + + diff --git a/apps/mobile/android/app/src/main/res/mipmap-hdpi/ic_launcher.png b/apps/mobile/android/app/src/main/res/mipmap-hdpi/ic_launcher.png new file mode 100644 index 0000000000000000000000000000000000000000..db77bb4b7b0906d62b1847e87f15cdcacf6a4f29 GIT binary patch literal 544 zcmeAS@N?(olHy`uVBq!ia0vp^9w5xY3?!3`olAj~WQl7;NpOBzNqJ&XDuZK6ep0G} zXKrG8YEWuoN@d~6R2!h8bpbvhu0Wd6uZuB!w&u2PAxD2eNXD>P5D~Wn-+_Wa#27Xc zC?Zj|6r#X(-D3u$NCt}(Ms06KgJ4FxJVv{GM)!I~&n8Bnc94O7-Hd)cjDZswgC;Qs zO=b+9!WcT8F?0rF7!Uys2bs@gozCP?z~o%U|N3vA*22NaGQG zlg@K`O_XuxvZ&Ks^m&R!`&1=spLvfx7oGDKDwpwW`#iqdw@AL`7MR}m`rwr|mZgU`8P7SBkL78fFf!WnuYWm$5Z0 zNXhDbCv&49sM544K|?c)WrFfiZvCi9h0O)B3Pgg&ebxsLQ05GG~ AQ2+n{ literal 0 HcmV?d00001 diff --git a/apps/mobile/android/app/src/main/res/mipmap-mdpi/ic_launcher.png b/apps/mobile/android/app/src/main/res/mipmap-mdpi/ic_launcher.png new file mode 100644 index 0000000000000000000000000000000000000000..17987b79bb8a35cc66c3c1fd44f5a5526c1b78be GIT binary patch literal 442 zcmeAS@N?(olHy`uVBq!ia0vp^1|ZDA3?vioaBc-sk|nMYCBgY=CFO}lsSJ)O`AMk? zp1FzXsX?iUDV2pMQ*D5Xx&nMcT!A!W`0S9QKQy;}1Cl^CgaH=;G9cpY;r$Q>i*pfB zP2drbID<_#qf;rPZx^FqH)F_D#*k@@q03KywUtLX8Ua?`H+NMzkczFPK3lFz@i_kW%1NOn0|D2I9n9wzH8m|-tHjsw|9>@K=iMBhxvkv6m8Y-l zytQ?X=U+MF$@3 zt`~i=@j|6y)RWMK--}M|=T`o&^Ni>IoWKHEbBXz7?A@mgWoL>!*SXo`SZH-*HSdS+ yn*9;$7;m`l>wYBC5bq;=U}IMqLzqbYCidGC!)_gkIk_C@Uy!y&wkt5C($~2D>~)O*cj@FGjOCM)M>_ixfudOh)?xMu#Fs z#}Y=@YDTwOM)x{K_j*Q;dPdJ?Mz0n|pLRx{4n|)f>SXlmV)XB04CrSJn#dS5nK2lM zrZ9#~WelCp7&e13Y$jvaEXHskn$2V!!DN-nWS__6T*l;H&Fopn?A6HZ-6WRLFP=R` zqG+CE#d4|IbyAI+rJJ`&x9*T`+a=p|0O(+s{UBcyZdkhj=yS1>AirP+0R;mf2uMgM zC}@~JfByORAh4SyRgi&!(cja>F(l*O+nd+@4m$|6K6KDn_&uvCpV23&>G9HJp{xgg zoq1^2_p9@|WEo z*X_Uko@K)qYYv~>43eQGMdbiGbo>E~Q& zrYBH{QP^@Sti!`2)uG{irBBq@y*$B zi#&(U-*=fp74j)RyIw49+0MRPMRU)+a2r*PJ$L5roHt2$UjExCTZSbq%V!HeS7J$N zdG@vOZB4v_lF7Plrx+hxo7(fCV&}fHq)$ literal 0 HcmV?d00001 diff --git a/apps/mobile/android/app/src/main/res/mipmap-xxhdpi/ic_launcher.png b/apps/mobile/android/app/src/main/res/mipmap-xxhdpi/ic_launcher.png new file mode 100644 index 0000000000000000000000000000000000000000..d5f1c8d34e7a88e3f88bea192c3a370d44689c3c GIT binary patch literal 1031 zcmeAS@N?(olHy`uVBq!ia0vp^6F``Q8Ax83A=Cw=BuiW)N`mv#O3D+9QW+dm@{>{( zJaZG%Q-e|yQz{EjrrIztFa`(sgt!6~Yi|1%a`XoT0ojZ}lNrNjb9xjc(B0U1_% zz5^97Xt*%oq$rQy4?0GKNfJ44uvxI)gC`h-NZ|&0-7(qS@?b!5r36oQ}zyZrNO3 zMO=Or+<~>+A&uN&E!^Sl+>xE!QC-|oJv`ApDhqC^EWD|@=#J`=d#Xzxs4ah}w&Jnc z$|q_opQ^2TrnVZ0o~wh<3t%W&flvYGe#$xqda2bR_R zvPYgMcHgjZ5nSA^lJr%;<&0do;O^tDDh~=pIxA#coaCY>&N%M2^tq^U%3DB@ynvKo}b?yu-bFc-u0JHzced$sg7S3zqI(2 z#Km{dPr7I=pQ5>FuK#)QwK?Y`E`B?nP+}U)I#c1+FM*1kNvWG|a(TpksZQ3B@sD~b zpQ2)*V*TdwjFOtHvV|;OsiDqHi=6%)o4b!)x$)%9pGTsE z-JL={-Ffv+T87W(Xpooq<`r*VzWQcgBN$$`u}f>-ZQI1BB8ykN*=e4rIsJx9>z}*o zo~|9I;xof literal 0 HcmV?d00001 diff --git a/apps/mobile/android/app/src/main/res/mipmap-xxxhdpi/ic_launcher.png b/apps/mobile/android/app/src/main/res/mipmap-xxxhdpi/ic_launcher.png new file mode 100644 index 0000000000000000000000000000000000000000..4d6372eebdb28e45604e46eeda8dd24651419bc0 GIT binary patch literal 1443 zcmb`G{WsKk6vsdJTdFg%tJav9_E4vzrOaqkWF|A724Nly!y+?N9`YV6wZ}5(X(D_N(?!*n3`|_r0Hc?=PQw&*vnU?QTFY zB_MsH|!j$PP;I}?dppoE_gA(4uc!jV&0!l7_;&p2^pxNo>PEcNJv za5_RT$o2Mf!<+r?&EbHH6nMoTsDOa;mN(wv8RNsHpG)`^ymG-S5By8=l9iVXzN_eG%Xg2@Xeq76tTZ*dGh~Lo9vl;Zfs+W#BydUw zCkZ$o1LqWQO$FC9aKlLl*7x9^0q%0}$OMlp@Kk_jHXOjofdePND+j!A{q!8~Jn+s3 z?~~w@4?egS02}8NuulUA=L~QQfm;MzCGd)XhiftT;+zFO&JVyp2mBww?;QByS_1w! zrQlx%{^cMj0|Bo1FjwY@Q8?Hx0cIPF*@-ZRFpPc#bBw{5@tD(5%sClzIfl8WU~V#u zm5Q;_F!wa$BSpqhN>W@2De?TKWR*!ujY;Yylk_X5#~V!L*Gw~;$%4Q8~Mad z@`-kG?yb$a9cHIApZDVZ^U6Xkp<*4rU82O7%}0jjHlK{id@?-wpN*fCHXyXh(bLt* zPc}H-x0e4E&nQ>y%B-(EL=9}RyC%MyX=upHuFhAk&MLbsF0LP-q`XnH78@fT+pKPW zu72MW`|?8ht^tz$iC}ZwLp4tB;Q49K!QCF3@!iB1qOI=?w z7In!}F~ij(18UYUjnbmC!qKhPo%24?8U1x{7o(+?^Zu0Hx81|FuS?bJ0jgBhEMzf< zCgUq7r2OCB(`XkKcN-TL>u5y#dD6D!)5W?`O5)V^>jb)P)GBdy%t$uUMpf$SNV31$ zb||OojAbvMP?T@$h_ZiFLFVHDmbyMhJF|-_)HX3%m=CDI+ID$0^C>kzxprBW)hw(v zr!Gmda);ICoQyhV_oP5+C%?jcG8v+D@9f?Dk*!BxY}dazmrT@64UrP3hlslANK)bq z$67n83eh}OeW&SV@HG95P|bjfqJ7gw$e+`Hxo!4cx`jdK1bJ>YDSpGKLPZ^1cv$ek zIB?0S<#tX?SJCLWdMd{-ME?$hc7A$zBOdIJ)4!KcAwb=VMov)nK;9z>x~rfT1>dS+ zZ6#`2v@`jgbqq)P22H)Tx2CpmM^o1$B+xT6`(v%5xJ(?j#>Q$+rx_R|7TzDZe{J6q zG1*EcU%tE?!kO%^M;3aM6JN*LAKUVb^xz8-Pxo#jR5(-KBeLJvA@-gxNHx0M-ZJLl z;#JwQoh~9V?`UVo#}{6ka@II>++D@%KqGpMdlQ}?9E*wFcf5(#XQnP$Dk5~%iX^>f z%$y;?M0BLp{O3a(-4A?ewryHrrD%cx#Q^%KY1H zNre$ve+vceSLZcNY4U(RBX&)oZn*Py()h)XkE?PL$!bNb{N5FVI2Y%LKEm%yvpyTP z(1P?z~7YxD~Rf<(a@_y` literal 0 HcmV?d00001 diff --git a/apps/mobile/android/app/src/main/res/values-night/styles.xml b/apps/mobile/android/app/src/main/res/values-night/styles.xml new file mode 100644 index 0000000..06952be --- /dev/null +++ b/apps/mobile/android/app/src/main/res/values-night/styles.xml @@ -0,0 +1,18 @@ + + + + + + + diff --git a/apps/mobile/android/app/src/main/res/values/styles.xml b/apps/mobile/android/app/src/main/res/values/styles.xml new file mode 100644 index 0000000..cb1ef88 --- /dev/null +++ b/apps/mobile/android/app/src/main/res/values/styles.xml @@ -0,0 +1,18 @@ + + + + + + + diff --git a/apps/mobile/android/app/src/profile/AndroidManifest.xml b/apps/mobile/android/app/src/profile/AndroidManifest.xml new file mode 100644 index 0000000..399f698 --- /dev/null +++ b/apps/mobile/android/app/src/profile/AndroidManifest.xml @@ -0,0 +1,7 @@ + + + + diff --git a/apps/mobile/android/build.gradle.kts b/apps/mobile/android/build.gradle.kts new file mode 100644 index 0000000..dbee657 --- /dev/null +++ b/apps/mobile/android/build.gradle.kts @@ -0,0 +1,24 @@ +allprojects { + repositories { + google() + mavenCentral() + } +} + +val newBuildDir: Directory = + rootProject.layout.buildDirectory + .dir("../../build") + .get() +rootProject.layout.buildDirectory.value(newBuildDir) + +subprojects { + val newSubprojectBuildDir: Directory = newBuildDir.dir(project.name) + project.layout.buildDirectory.value(newSubprojectBuildDir) +} +subprojects { + project.evaluationDependsOn(":app") +} + +tasks.register("clean") { + delete(rootProject.layout.buildDirectory) +} diff --git a/apps/mobile/android/gradle.properties b/apps/mobile/android/gradle.properties new file mode 100644 index 0000000..fbee1d8 --- /dev/null +++ b/apps/mobile/android/gradle.properties @@ -0,0 +1,2 @@ +org.gradle.jvmargs=-Xmx8G -XX:MaxMetaspaceSize=4G -XX:ReservedCodeCacheSize=512m -XX:+HeapDumpOnOutOfMemoryError +android.useAndroidX=true diff --git a/apps/mobile/android/gradle/wrapper/gradle-wrapper.properties b/apps/mobile/android/gradle/wrapper/gradle-wrapper.properties new file mode 100644 index 0000000..e4ef43f --- /dev/null +++ b/apps/mobile/android/gradle/wrapper/gradle-wrapper.properties @@ -0,0 +1,5 @@ +distributionBase=GRADLE_USER_HOME +distributionPath=wrapper/dists +zipStoreBase=GRADLE_USER_HOME +zipStorePath=wrapper/dists +distributionUrl=https\://services.gradle.org/distributions/gradle-8.14-all.zip diff --git a/apps/mobile/android/settings.gradle.kts b/apps/mobile/android/settings.gradle.kts new file mode 100644 index 0000000..ca7fe06 --- /dev/null +++ b/apps/mobile/android/settings.gradle.kts @@ -0,0 +1,26 @@ +pluginManagement { + val flutterSdkPath = + run { + val properties = java.util.Properties() + file("local.properties").inputStream().use { properties.load(it) } + val flutterSdkPath = properties.getProperty("flutter.sdk") + require(flutterSdkPath != null) { "flutter.sdk not set in local.properties" } + flutterSdkPath + } + + includeBuild("$flutterSdkPath/packages/flutter_tools/gradle") + + repositories { + google() + mavenCentral() + gradlePluginPortal() + } +} + +plugins { + id("dev.flutter.flutter-plugin-loader") version "1.0.0" + id("com.android.application") version "8.11.1" apply false + id("org.jetbrains.kotlin.android") version "2.2.20" apply false +} + +include(":app") diff --git a/apps/mobile/assets/fonts/JetBrainsMono-Bold.ttf b/apps/mobile/assets/fonts/JetBrainsMono-Bold.ttf new file mode 100644 index 0000000000000000000000000000000000000000..cd1bee0704e05a899cd70f0640a801f1afe046b2 GIT binary patch literal 274096 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 Mj&EQ!95U?x06XQQjsO4v literal 0 HcmV?d00001 diff --git a/apps/mobile/assets/fonts/JetBrainsMono-Regular.ttf b/apps/mobile/assets/fonts/JetBrainsMono-Regular.ttf new file mode 100644 index 0000000000000000000000000000000000000000..711830ede02a366f8b99f88e52f3148405e67eaf GIT binary patch literal 270224 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

{Qq;dYoLXG*oL7!{wrG%~aKb=FoR7{s=k| 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

AzPi!HK1CYdMasJ%868x!dF;`ny|>LRT>eY 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 { + return const FlutterSecureStorage(); +}); + +final _tokenStorageProvider = Provider((ref) { + return TokenStorage(ref.read(_secureStorageProvider)); +}); + +final _gitHubOAuthProvider = Provider((ref) { + return const GitHubOAuth(); +}); + +// --------------------------------------------------------------------------- +// Repository provider +// --------------------------------------------------------------------------- + +final authRepositoryProvider = Provider((ref) { + return AuthRepository( + tokenStorage: ref.read(_tokenStorageProvider), + gitHubOAuth: ref.read(_gitHubOAuthProvider), + ); +}); + +// --------------------------------------------------------------------------- +// AuthStateNotifier +// --------------------------------------------------------------------------- + +class AuthStateNotifier extends StateNotifier { + AuthStateNotifier(this._repository) : super(const AuthState()); + + final AuthRepository _repository; + + Future restoreSession() async { + state = state.copyWith(status: AuthStatus.loading); + try { + final authenticated = await _repository.isAuthenticated(); + if (authenticated) { + final token = await _repository.getStoredToken(); + state = state.copyWith( + status: AuthStatus.authenticated, + accessToken: token, + tokenType: 'pat', + ); + } else { + state = state.copyWith(status: AuthStatus.unauthenticated); + } + } catch (e) { + state = state.copyWith( + status: AuthStatus.error, + errorMessage: e.toString(), + ); + } + } + + Future signInWithOAuth(String code) async { + state = state.copyWith(status: AuthStatus.loading, errorMessage: null); + try { + await _repository.signInWithOAuth(code); + final token = await _repository.getStoredToken(); + state = state.copyWith( + status: AuthStatus.authenticated, + accessToken: token, + tokenType: 'oauth', + ); + } catch (e) { + state = state.copyWith( + status: AuthStatus.error, + errorMessage: e.toString(), + ); + } + } + + Future signInWithPAT(String token) async { + state = state.copyWith(status: AuthStatus.loading, errorMessage: null); + try { + final profile = await _repository.signInWithPAT(token); + state = state.copyWith( + status: AuthStatus.authenticated, + accessToken: token, + username: profile['login'], + avatarUrl: profile['avatar_url'], + tokenType: 'pat', + ); + } catch (e) { + state = state.copyWith( + status: AuthStatus.error, + errorMessage: e.toString(), + ); + } + } + + Future signOut() async { + await _repository.signOut(); + state = const AuthState(status: AuthStatus.unauthenticated); + } +} + +// --------------------------------------------------------------------------- +// AuthState provider +// --------------------------------------------------------------------------- + +final authStateProvider = + StateNotifierProvider((ref) { + return AuthStateNotifier(ref.read(authRepositoryProvider)); +}); diff --git a/apps/mobile/lib/core/auth/auth_repository.dart b/apps/mobile/lib/core/auth/auth_repository.dart new file mode 100644 index 0000000..49c367d --- /dev/null +++ b/apps/mobile/lib/core/auth/auth_repository.dart @@ -0,0 +1,49 @@ +import 'token_storage.dart'; +import 'github_oauth.dart'; + +/// Repository layer for authentication operations. +/// Coordinates between [TokenStorage] and [GitHubOAuth]. +class AuthRepository { + const AuthRepository({ + required TokenStorage tokenStorage, + required GitHubOAuth gitHubOAuth, + }) : _storage = tokenStorage, + _oauth = gitHubOAuth; + + final TokenStorage _storage; + final GitHubOAuth _oauth; + + /// Exchange an OAuth code for a token and persist it. + Future signInWithOAuth(String code) async { + final token = await _oauth.handleCallback(code); + await _storage.saveToken(kAuthToken, token); + await _storage.saveToken(kRefreshToken, ''); // refresh not used for PAT + } + + /// Validate and persist a GitHub Personal Access Token. + Future> signInWithPAT(String token) async { + final valid = await _oauth.validatePAT(token); + if (!valid) { + throw Exception('Invalid Personal Access Token'); + } + await _storage.saveToken(kAuthToken, token); + final profile = await _oauth.fetchUserProfile(token); + return profile; + } + + /// Remove all stored tokens. + Future signOut() async { + await _storage.clearAll(); + } + + /// Return the stored auth token (or null if not signed in). + Future getStoredToken() async { + return _storage.getToken(kAuthToken); + } + + /// Returns true if a non-empty auth token is present in storage. + Future isAuthenticated() async { + final token = await getStoredToken(); + return token != null && token.isNotEmpty; + } +} diff --git a/apps/mobile/lib/core/auth/auth_state.dart b/apps/mobile/lib/core/auth/auth_state.dart new file mode 100644 index 0000000..5855b00 --- /dev/null +++ b/apps/mobile/lib/core/auth/auth_state.dart @@ -0,0 +1,17 @@ +import 'package:freezed_annotation/freezed_annotation.dart'; + +part 'auth_state.freezed.dart'; + +enum AuthStatus { unauthenticated, authenticated, loading, error } + +@freezed +class AuthState with _$AuthState { + const factory AuthState({ + @Default(AuthStatus.unauthenticated) AuthStatus status, + String? accessToken, + String? username, + String? avatarUrl, + String? tokenType, // "oauth" | "pat" + String? errorMessage, + }) = _AuthState; +} diff --git a/apps/mobile/lib/core/auth/auth_state.freezed.dart b/apps/mobile/lib/core/auth/auth_state.freezed.dart new file mode 100644 index 0000000..d209782 --- /dev/null +++ b/apps/mobile/lib/core/auth/auth_state.freezed.dart @@ -0,0 +1,255 @@ +// coverage:ignore-file +// GENERATED CODE - DO NOT MODIFY BY HAND +// ignore_for_file: type=lint +// ignore_for_file: unused_element, deprecated_member_use, deprecated_member_use_from_same_package, use_function_type_syntax_for_parameters, unnecessary_const, avoid_init_to_null, invalid_override_different_default_values_named, prefer_expression_function_bodies, annotate_overrides, invalid_annotation_target, unnecessary_question_mark + +part of 'auth_state.dart'; + +// ************************************************************************** +// FreezedGenerator +// ************************************************************************** + +T _$identity(T value) => value; + +final _privateConstructorUsedError = UnsupportedError( + 'It seems like you constructed your class using `MyClass._()`. This constructor is only meant to be used by freezed and you are not supposed to need it nor use it.\nPlease check the documentation here for more information: https://github.com/rrousselGit/freezed#adding-getters-and-methods-to-our-models'); + +/// @nodoc +mixin _$AuthState { + AuthStatus get status => throw _privateConstructorUsedError; + String? get accessToken => throw _privateConstructorUsedError; + String? get username => throw _privateConstructorUsedError; + String? get avatarUrl => throw _privateConstructorUsedError; + String? get tokenType => + throw _privateConstructorUsedError; // "oauth" | "pat" + String? get errorMessage => throw _privateConstructorUsedError; + + /// Create a copy of AuthState + /// with the given fields replaced by the non-null parameter values. + @JsonKey(includeFromJson: false, includeToJson: false) + $AuthStateCopyWith get copyWith => + throw _privateConstructorUsedError; +} + +/// @nodoc +abstract class $AuthStateCopyWith<$Res> { + factory $AuthStateCopyWith(AuthState value, $Res Function(AuthState) then) = + _$AuthStateCopyWithImpl<$Res, AuthState>; + @useResult + $Res call( + {AuthStatus status, + String? accessToken, + String? username, + String? avatarUrl, + String? tokenType, + String? errorMessage}); +} + +/// @nodoc +class _$AuthStateCopyWithImpl<$Res, $Val extends AuthState> + implements $AuthStateCopyWith<$Res> { + _$AuthStateCopyWithImpl(this._value, this._then); + + // ignore: unused_field + final $Val _value; + // ignore: unused_field + final $Res Function($Val) _then; + + /// Create a copy of AuthState + /// with the given fields replaced by the non-null parameter values. + @pragma('vm:prefer-inline') + @override + $Res call({ + Object? status = null, + Object? accessToken = freezed, + Object? username = freezed, + Object? avatarUrl = freezed, + Object? tokenType = freezed, + Object? errorMessage = freezed, + }) { + return _then(_value.copyWith( + status: null == status + ? _value.status + : status // ignore: cast_nullable_to_non_nullable + as AuthStatus, + accessToken: freezed == accessToken + ? _value.accessToken + : accessToken // ignore: cast_nullable_to_non_nullable + as String?, + username: freezed == username + ? _value.username + : username // ignore: cast_nullable_to_non_nullable + as String?, + avatarUrl: freezed == avatarUrl + ? _value.avatarUrl + : avatarUrl // ignore: cast_nullable_to_non_nullable + as String?, + tokenType: freezed == tokenType + ? _value.tokenType + : tokenType // ignore: cast_nullable_to_non_nullable + as String?, + errorMessage: freezed == errorMessage + ? _value.errorMessage + : errorMessage // ignore: cast_nullable_to_non_nullable + as String?, + ) as $Val); + } +} + +/// @nodoc +abstract class _$$AuthStateImplCopyWith<$Res> + implements $AuthStateCopyWith<$Res> { + factory _$$AuthStateImplCopyWith( + _$AuthStateImpl value, $Res Function(_$AuthStateImpl) then) = + __$$AuthStateImplCopyWithImpl<$Res>; + @override + @useResult + $Res call( + {AuthStatus status, + String? accessToken, + String? username, + String? avatarUrl, + String? tokenType, + String? errorMessage}); +} + +/// @nodoc +class __$$AuthStateImplCopyWithImpl<$Res> + extends _$AuthStateCopyWithImpl<$Res, _$AuthStateImpl> + implements _$$AuthStateImplCopyWith<$Res> { + __$$AuthStateImplCopyWithImpl( + _$AuthStateImpl _value, $Res Function(_$AuthStateImpl) _then) + : super(_value, _then); + + /// Create a copy of AuthState + /// with the given fields replaced by the non-null parameter values. + @pragma('vm:prefer-inline') + @override + $Res call({ + Object? status = null, + Object? accessToken = freezed, + Object? username = freezed, + Object? avatarUrl = freezed, + Object? tokenType = freezed, + Object? errorMessage = freezed, + }) { + return _then(_$AuthStateImpl( + status: null == status + ? _value.status + : status // ignore: cast_nullable_to_non_nullable + as AuthStatus, + accessToken: freezed == accessToken + ? _value.accessToken + : accessToken // ignore: cast_nullable_to_non_nullable + as String?, + username: freezed == username + ? _value.username + : username // ignore: cast_nullable_to_non_nullable + as String?, + avatarUrl: freezed == avatarUrl + ? _value.avatarUrl + : avatarUrl // ignore: cast_nullable_to_non_nullable + as String?, + tokenType: freezed == tokenType + ? _value.tokenType + : tokenType // ignore: cast_nullable_to_non_nullable + as String?, + errorMessage: freezed == errorMessage + ? _value.errorMessage + : errorMessage // ignore: cast_nullable_to_non_nullable + as String?, + )); + } +} + +/// @nodoc + +class _$AuthStateImpl implements _AuthState { + const _$AuthStateImpl( + {this.status = AuthStatus.unauthenticated, + this.accessToken, + this.username, + this.avatarUrl, + this.tokenType, + this.errorMessage}); + + @override + @JsonKey() + final AuthStatus status; + @override + final String? accessToken; + @override + final String? username; + @override + final String? avatarUrl; + @override + final String? tokenType; +// "oauth" | "pat" + @override + final String? errorMessage; + + @override + String toString() { + return 'AuthState(status: $status, accessToken: $accessToken, username: $username, avatarUrl: $avatarUrl, tokenType: $tokenType, errorMessage: $errorMessage)'; + } + + @override + bool operator ==(Object other) { + return identical(this, other) || + (other.runtimeType == runtimeType && + other is _$AuthStateImpl && + (identical(other.status, status) || other.status == status) && + (identical(other.accessToken, accessToken) || + other.accessToken == accessToken) && + (identical(other.username, username) || + other.username == username) && + (identical(other.avatarUrl, avatarUrl) || + other.avatarUrl == avatarUrl) && + (identical(other.tokenType, tokenType) || + other.tokenType == tokenType) && + (identical(other.errorMessage, errorMessage) || + other.errorMessage == errorMessage)); + } + + @override + int get hashCode => Object.hash(runtimeType, status, accessToken, username, + avatarUrl, tokenType, errorMessage); + + /// Create a copy of AuthState + /// with the given fields replaced by the non-null parameter values. + @JsonKey(includeFromJson: false, includeToJson: false) + @override + @pragma('vm:prefer-inline') + _$$AuthStateImplCopyWith<_$AuthStateImpl> get copyWith => + __$$AuthStateImplCopyWithImpl<_$AuthStateImpl>(this, _$identity); +} + +abstract class _AuthState implements AuthState { + const factory _AuthState( + {final AuthStatus status, + final String? accessToken, + final String? username, + final String? avatarUrl, + final String? tokenType, + final String? errorMessage}) = _$AuthStateImpl; + + @override + AuthStatus get status; + @override + String? get accessToken; + @override + String? get username; + @override + String? get avatarUrl; + @override + String? get tokenType; // "oauth" | "pat" + @override + String? get errorMessage; + + /// Create a copy of AuthState + /// with the given fields replaced by the non-null parameter values. + @override + @JsonKey(includeFromJson: false, includeToJson: false) + _$$AuthStateImplCopyWith<_$AuthStateImpl> get copyWith => + throw _privateConstructorUsedError; +} diff --git a/apps/mobile/lib/core/auth/github_oauth.dart b/apps/mobile/lib/core/auth/github_oauth.dart new file mode 100644 index 0000000..2c0295e --- /dev/null +++ b/apps/mobile/lib/core/auth/github_oauth.dart @@ -0,0 +1,98 @@ +import 'dart:convert'; +import 'package:http/http.dart' as http; + +// --------------------------------------------------------------------------- +// IMPORTANT: OAuth exchange requires the client secret, which must NEVER be +// embedded in the mobile app binary. A proper production implementation routes +// the code→token exchange through a server-side endpoint that holds the secret. +// This class documents the flow; the `handleCallback` method is a placeholder +// that highlights this constraint. +// --------------------------------------------------------------------------- + +// Replace with your actual GitHub OAuth App credentials. +// The client secret MUST be stored server-side only. +const String _kGitHubClientId = 'YOUR_GITHUB_CLIENT_ID'; +const String _kRedirectUri = 'recursor://auth/callback'; + +/// Handles GitHub OAuth login and Personal Access Token (PAT) validation. +class GitHubOAuth { + const GitHubOAuth(); + + /// Returns the GitHub Authorization URL to open in a WebView. + /// + /// After the user authorizes, GitHub redirects to [_kRedirectUri] with a + /// `?code=` parameter. Pass that code to [handleCallback]. + String startOAuthFlow() { + final params = Uri(queryParameters: { + 'client_id': _kGitHubClientId, + 'redirect_uri': _kRedirectUri, + 'scope': 'read:user repo', + 'state': DateTime.now().millisecondsSinceEpoch.toString(), + }).query; + + return 'https://github.com/login/oauth/authorize?$params'; + } + + /// Exchange the OAuth [code] for an access token. + /// + /// NOTE: This call requires the client secret. In production, proxy the + /// exchange through a first-party backend endpoint (e.g. POST /auth/github). + /// The implementation below is intentionally left as a commented-out stub. + Future handleCallback(String code) async { + // TODO(server-side): Route this through a backend endpoint that holds the + // client secret. Direct exchange from the mobile client is insecure. + // + // Example server-side call: + // POST https://your-backend.example.com/auth/github/callback + // Body: { "code": code } + // Response: { "access_token": "gho_xxx" } + throw UnimplementedError( + 'OAuth code exchange must be performed server-side to protect the ' + 'client secret. Implement a backend endpoint that exchanges the code ' + 'and returns the access token to the mobile client.', + ); + } + + /// Validate a GitHub Personal Access Token against the GitHub API. + /// + /// Returns `true` if the token is valid (i.e. the `/user` endpoint responds + /// with HTTP 200). + Future validatePAT(String token) async { + try { + final response = await http.get( + Uri.parse('https://api.github.com/user'), + headers: { + 'Authorization': 'Bearer $token', + 'Accept': 'application/vnd.github+json', + 'X-GitHub-Api-Version': '2022-11-28', + }, + ); + return response.statusCode == 200; + } catch (_) { + return false; + } + } + + /// Fetch the authenticated user's profile using a validated token. + /// Returns a map with `login` and `avatar_url` fields. + Future> fetchUserProfile(String token) async { + final response = await http.get( + Uri.parse('https://api.github.com/user'), + headers: { + 'Authorization': 'Bearer $token', + 'Accept': 'application/vnd.github+json', + 'X-GitHub-Api-Version': '2022-11-28', + }, + ); + + if (response.statusCode != 200) { + throw Exception('GitHub API error: ${response.statusCode}'); + } + + final body = jsonDecode(response.body) as Map; + return { + 'login': body['login'] as String? ?? '', + 'avatar_url': body['avatar_url'] as String? ?? '', + }; + } +} diff --git a/apps/mobile/lib/core/auth/token_storage.dart b/apps/mobile/lib/core/auth/token_storage.dart new file mode 100644 index 0000000..5d8136e --- /dev/null +++ b/apps/mobile/lib/core/auth/token_storage.dart @@ -0,0 +1,29 @@ +import 'package:flutter_secure_storage/flutter_secure_storage.dart'; + +const String kAuthToken = 'auth_token'; +const String kRefreshToken = 'refresh_token'; +const String kBridgeToken = 'bridge_token'; + +/// Secure key-value storage for authentication tokens. +/// Backed by [FlutterSecureStorage] (Keychain on iOS, Keystore on Android). +class TokenStorage { + const TokenStorage(this._storage); + + final FlutterSecureStorage _storage; + + Future saveToken(String key, String value) async { + await _storage.write(key: key, value: value); + } + + Future getToken(String key) async { + return _storage.read(key: key); + } + + Future deleteToken(String key) async { + await _storage.delete(key: key); + } + + Future clearAll() async { + await _storage.deleteAll(); + } +} diff --git a/apps/mobile/lib/core/config/app_config.dart b/apps/mobile/lib/core/config/app_config.dart new file mode 100644 index 0000000..1b1eb66 --- /dev/null +++ b/apps/mobile/lib/core/config/app_config.dart @@ -0,0 +1,19 @@ +/// Application-wide constants. +class AppConfig { + const AppConfig._(); + + static const String appName = 'ReCursor'; + static const String version = '0.1.0'; + + /// Heartbeat ping interval in seconds. + static const int heartbeatInterval = 15; + + /// Seconds to wait for a heartbeat pong before triggering reconnect. + static const int heartbeatTimeout = 10; + + /// Maximum number of reconnect attempts before giving up. + static const int maxReconnectAttempts = 10; + + /// Maximum number of items stored in the offline sync queue. + static const int maxSyncQueueSize = 500; +} diff --git a/apps/mobile/lib/core/config/high_contrast_theme.dart b/apps/mobile/lib/core/config/high_contrast_theme.dart new file mode 100644 index 0000000..6815fe4 --- /dev/null +++ b/apps/mobile/lib/core/config/high_contrast_theme.dart @@ -0,0 +1,56 @@ +import 'package:flutter/material.dart'; + +class HighContrastTheme { + static ThemeData get theme { + return ThemeData.dark().copyWith( + colorScheme: const ColorScheme.dark( + primary: Color(0xFFFFFFFF), // white + secondary: Color(0xFFFFFF00), // yellow + surface: Color(0xFF000000), // pure black + error: Color(0xFFFF0000), // pure red + ), + scaffoldBackgroundColor: Colors.black, + cardTheme: const CardThemeData( + color: Color(0xFF111111), + elevation: 0, + shape: RoundedRectangleBorder( + side: BorderSide(color: Colors.white, width: 1), + ), + ), + appBarTheme: const AppBarTheme( + backgroundColor: Colors.black, + foregroundColor: Colors.white, + elevation: 0, + shape: Border(bottom: BorderSide(color: Colors.white, width: 1)), + ), + textTheme: const TextTheme( + bodyLarge: TextStyle(color: Colors.white, fontSize: 16), + bodyMedium: TextStyle(color: Colors.white, fontSize: 14), + bodySmall: TextStyle(color: Colors.white, fontSize: 12), + titleLarge: TextStyle(color: Colors.white, fontWeight: FontWeight.bold), + ), + iconTheme: const IconThemeData(color: Colors.white), + dividerColor: Colors.white, + inputDecorationTheme: InputDecorationTheme( + filled: true, + fillColor: Colors.black, + border: const OutlineInputBorder( + borderSide: BorderSide(color: Colors.white, width: 2), + ), + enabledBorder: const OutlineInputBorder( + borderSide: BorderSide(color: Colors.white, width: 2), + ), + focusedBorder: const OutlineInputBorder( + borderSide: BorderSide(color: Colors.yellow, width: 2), + ), + labelStyle: const TextStyle(color: Colors.white), + hintStyle: const TextStyle(color: Colors.grey), + ), + bottomNavigationBarTheme: const BottomNavigationBarThemeData( + backgroundColor: Colors.black, + selectedItemColor: Colors.yellow, + unselectedItemColor: Colors.white, + ), + ); + } +} diff --git a/apps/mobile/lib/core/config/router.dart b/apps/mobile/lib/core/config/router.dart new file mode 100644 index 0000000..7068021 --- /dev/null +++ b/apps/mobile/lib/core/config/router.dart @@ -0,0 +1,324 @@ +import 'package:flutter/material.dart'; +import 'package:flutter_riverpod/flutter_riverpod.dart'; +import 'package:go_router/go_router.dart'; + +import '../auth/auth_provider.dart'; +import '../auth/auth_state.dart'; +import '../network/connection_state.dart' as cs; +import '../providers/websocket_provider.dart'; +import '../../features/auth/presentation/screens/splash_screen.dart'; +import '../../features/auth/presentation/screens/login_screen.dart'; +import '../../features/auth/presentation/screens/bridge_setup_screen.dart'; +import '../../features/chat/presentation/screens/session_list_screen.dart'; +import '../../features/chat/presentation/screens/chat_screen.dart'; +import '../../features/diff/presentation/screens/diff_viewer_screen.dart'; +import '../../features/repos/presentation/screens/file_tree_screen.dart'; +import '../../features/repos/presentation/screens/file_viewer_screen.dart'; + +// --------------------------------------------------------------------------- +// Placeholder screens +// --------------------------------------------------------------------------- + +class _GitScreen extends StatelessWidget { + const _GitScreen(); + + @override + Widget build(BuildContext context) { + return Scaffold( + appBar: AppBar(title: const Text('Git')), + body: const Center(child: Text('Git')), + ); + } +} + +class _ApprovalsScreen extends StatelessWidget { + const _ApprovalsScreen(); + + @override + Widget build(BuildContext context) { + return Scaffold( + appBar: AppBar(title: const Text('Approvals')), + body: const Center(child: Text('Approvals')), + ); + } +} + +class _SettingsScreen extends StatelessWidget { + const _SettingsScreen(); + + @override + Widget build(BuildContext context) { + return Scaffold( + appBar: AppBar(title: const Text('Settings')), + body: const Center(child: Text('Settings')), + ); + } +} + +class _AgentListScreen extends StatelessWidget { + const _AgentListScreen(); + + @override + Widget build(BuildContext context) { + return Scaffold( + appBar: AppBar(title: const Text('Agents')), + body: const Center(child: Text('Agents')), + ); + } +} + +class _ApprovalDetailScreen extends StatelessWidget { + final String id; + const _ApprovalDetailScreen({required this.id}); + + @override + Widget build(BuildContext context) { + return Scaffold( + appBar: AppBar(title: const Text('Approval Detail')), + body: Center(child: Text('Approval: $id')), + ); + } +} + +class _TerminalScreen extends StatelessWidget { + const _TerminalScreen(); + + @override + Widget build(BuildContext context) { + return Scaffold( + appBar: AppBar(title: const Text('Terminal')), + body: const Center(child: Text('Terminal')), + ); + } +} + +// --------------------------------------------------------------------------- +// Home shell +// --------------------------------------------------------------------------- + +class HomeShell extends ConsumerStatefulWidget { + final StatefulNavigationShell navigationShell; + const HomeShell({super.key, required this.navigationShell}); + + @override + ConsumerState createState() => _HomeShellState(); +} + +class _HomeShellState extends ConsumerState { + static const _items = [ + BottomNavigationBarItem(icon: Icon(Icons.chat), label: 'Chat'), + BottomNavigationBarItem(icon: Icon(Icons.difference), label: 'Diff'), + BottomNavigationBarItem(icon: Icon(Icons.folder_outlined), label: 'Files'), + BottomNavigationBarItem(icon: Icon(Icons.source), label: 'Git'), + BottomNavigationBarItem(icon: Icon(Icons.approval), label: 'Approvals'), + BottomNavigationBarItem(icon: Icon(Icons.settings), label: 'Settings'), + ]; + + @override + Widget build(BuildContext context) { + return Scaffold( + body: Column( + children: [ + const ConnectionStatusBar(), + Expanded(child: widget.navigationShell), + ], + ), + bottomNavigationBar: BottomNavigationBar( + currentIndex: widget.navigationShell.currentIndex, + items: _items, + onTap: (index) => widget.navigationShell.goBranch( + index, + initialLocation: index == widget.navigationShell.currentIndex, + ), + ), + ); + } +} + +// --------------------------------------------------------------------------- +// ConnectionStatusBar (inline — also exported from shared/widgets) +// --------------------------------------------------------------------------- + +class ConnectionStatusBar extends ConsumerWidget { + const ConnectionStatusBar({super.key}); + + @override + Widget build(BuildContext context, WidgetRef ref) { + final statusAsync = ref.watch(connectionStatusProvider); + return statusAsync.when( + data: (status) => _bar(status), + loading: () => const SizedBox.shrink(), + error: (_, __) => const SizedBox.shrink(), + ); + } + + Widget _bar(cs.ConnectionStatus status) { + if (status == cs.ConnectionStatus.connected) return const SizedBox.shrink(); + + final isReconnecting = status == cs.ConnectionStatus.reconnecting; + final color = isReconnecting ? const Color(0xFFFF9800) : const Color(0xFFF44747); + final message = isReconnecting ? 'Reconnecting...' : 'Offline'; + + return Container( + width: double.infinity, + color: color, + padding: const EdgeInsets.symmetric(vertical: 3), + child: Text( + message, + textAlign: TextAlign.center, + style: const TextStyle( + color: Colors.white, + fontSize: 12, + fontWeight: FontWeight.w500, + ), + ), + ); + } +} + +// --------------------------------------------------------------------------- +// Router +// --------------------------------------------------------------------------- + +GoRouter _buildRouter(AuthState authState) { + return GoRouter( + initialLocation: '/splash', + redirect: (context, state) { + final status = authState.status; + final location = state.matchedLocation; + + if (status == AuthStatus.loading) return null; + + if (status == AuthStatus.unauthenticated) { + if (location == '/login' || location == '/splash') return null; + return '/login'; + } + + if (status == AuthStatus.authenticated) { + if (location == '/login' || location == '/splash') { + return '/home/chat'; + } + } + + return null; + }, + routes: [ + GoRoute( + path: '/', + redirect: (_, __) => '/splash', + ), + GoRoute( + path: '/splash', + builder: (_, __) => const SplashScreen(), + ), + GoRoute( + path: '/login', + builder: (_, __) => const LoginScreen(), + ), + GoRoute( + path: '/bridge-setup', + builder: (_, __) => const BridgeSetupScreen(), + ), + StatefulShellRoute.indexedStack( + builder: (context, state, navigationShell) => + HomeShell(navigationShell: navigationShell), + branches: [ + StatefulShellBranch( + routes: [ + GoRoute( + path: '/home/chat', + builder: (_, __) => const SessionListScreen(), + routes: [ + GoRoute( + path: ':sessionId', + builder: (_, state) => ChatScreen( + sessionId: state.pathParameters['sessionId']!, + ), + ), + ], + ), + ], + ), + StatefulShellBranch( + routes: [ + GoRoute( + path: '/home/diff', + builder: (_, __) => const DiffViewerScreen(), + ), + ], + ), + StatefulShellBranch( + routes: [ + GoRoute( + path: '/home/repos', + builder: (_, state) { + final sessionId = + state.uri.queryParameters['sessionId'] ?? ''; + return FileTreeScreen(sessionId: sessionId); + }, + ), + ], + ), + StatefulShellBranch( + routes: [ + GoRoute( + path: '/home/git', + builder: (_, __) => const _GitScreen(), + ), + ], + ), + StatefulShellBranch( + routes: [ + GoRoute( + path: '/home/approvals', + builder: (_, __) => const _ApprovalsScreen(), + ), + ], + ), + StatefulShellBranch( + routes: [ + GoRoute( + path: '/home/settings', + builder: (_, __) => const _SettingsScreen(), + ), + ], + ), + ], + ), + GoRoute( + path: '/home/agents', + builder: (_, __) => const _AgentListScreen(), + ), + GoRoute( + path: '/approval/:id', + builder: (_, state) => + _ApprovalDetailScreen(id: state.pathParameters['id']!), + ), + GoRoute( + path: '/terminal', + builder: (_, __) => const _TerminalScreen(), + ), + GoRoute( + path: '/home/repos/view', + builder: (_, state) { + final extra = state.extra as Map? ?? {}; + return FileViewerScreen( + sessionId: extra['sessionId'] ?? '', + path: extra['path'] ?? '', + ); + }, + ), + ], + ); +} + +// --------------------------------------------------------------------------- +// Providers +// --------------------------------------------------------------------------- + +final routerProvider = Provider((ref) { + final authState = ref.watch(authStateProvider); + return _buildRouter(authState); +}); + +final appRouter = Provider((ref) => ref.watch(routerProvider)); diff --git a/apps/mobile/lib/core/config/theme.dart b/apps/mobile/lib/core/config/theme.dart new file mode 100644 index 0000000..59b6a98 --- /dev/null +++ b/apps/mobile/lib/core/config/theme.dart @@ -0,0 +1,173 @@ +import 'package:flutter/material.dart'; + +import 'high_contrast_theme.dart'; + +class AppColors { + static const background = Color(0xFF121212); + static const surface = Color(0xFF1E1E1E); + static const surfaceVariant = Color(0xFF252526); + static const primary = Color(0xFF569CD6); + static const secondary = Color(0xFF4EC9B0); + static const error = Color(0xFFF44747); + static const added = Color(0xFF4EC9B0); + static const removed = Color(0xFFF44747); + static const accent = Color(0xFFCE9178); + static const textPrimary = Color(0xFFD4D4D4); + static const textSecondary = Color(0xFF9E9E9E); + static const border = Color(0xFF3E3E3E); +} + +class AppTheme { + static ThemeData get darkTheme { + const colorScheme = ColorScheme.dark( + surface: AppColors.surface, + background: AppColors.background, + primary: AppColors.primary, + secondary: AppColors.secondary, + error: AppColors.error, + onSurface: AppColors.textPrimary, + onBackground: AppColors.textPrimary, + onPrimary: Colors.white, + onSecondary: Colors.white, + ); + + return ThemeData( + useMaterial3: true, + colorScheme: colorScheme, + scaffoldBackgroundColor: AppColors.background, + cardColor: AppColors.surfaceVariant, + cardTheme: const CardThemeData( + color: AppColors.surfaceVariant, + elevation: 2, + margin: EdgeInsets.zero, + ), + appBarTheme: const AppBarTheme( + backgroundColor: AppColors.surface, + elevation: 0, + foregroundColor: AppColors.textPrimary, + titleTextStyle: TextStyle( + color: AppColors.textPrimary, + fontSize: 16, + fontWeight: FontWeight.w600, + ), + iconTheme: IconThemeData(color: AppColors.textPrimary), + ), + bottomNavigationBarTheme: const BottomNavigationBarThemeData( + backgroundColor: AppColors.surface, + selectedItemColor: AppColors.primary, + unselectedItemColor: AppColors.textSecondary, + type: BottomNavigationBarType.fixed, + elevation: 0, + ), + inputDecorationTheme: InputDecorationTheme( + filled: true, + fillColor: AppColors.surfaceVariant, + border: OutlineInputBorder( + borderRadius: BorderRadius.circular(8), + borderSide: const BorderSide(color: AppColors.border), + ), + enabledBorder: OutlineInputBorder( + borderRadius: BorderRadius.circular(8), + borderSide: const BorderSide(color: AppColors.border), + ), + focusedBorder: OutlineInputBorder( + borderRadius: BorderRadius.circular(8), + borderSide: const BorderSide(color: AppColors.primary), + ), + errorBorder: OutlineInputBorder( + borderRadius: BorderRadius.circular(8), + borderSide: const BorderSide(color: AppColors.error), + ), + hintStyle: const TextStyle(color: AppColors.textSecondary), + labelStyle: const TextStyle(color: AppColors.textSecondary), + ), + textTheme: const TextTheme( + bodyMedium: TextStyle( + fontFamily: 'JetBrainsMono', + fontSize: 14, + color: AppColors.textPrimary, + ), + bodyLarge: TextStyle( + fontSize: 16, + color: AppColors.textPrimary, + ), + bodySmall: TextStyle( + fontSize: 12, + color: AppColors.textSecondary, + ), + titleLarge: TextStyle( + fontSize: 20, + fontWeight: FontWeight.w600, + color: AppColors.textPrimary, + ), + titleMedium: TextStyle( + fontSize: 16, + fontWeight: FontWeight.w500, + color: AppColors.textPrimary, + ), + titleSmall: TextStyle( + fontSize: 14, + fontWeight: FontWeight.w500, + color: AppColors.textPrimary, + ), + labelLarge: TextStyle( + fontSize: 14, + fontWeight: FontWeight.w500, + color: AppColors.textPrimary, + ), + labelMedium: TextStyle( + fontSize: 12, + fontWeight: FontWeight.w500, + color: AppColors.textSecondary, + ), + ), + iconTheme: const IconThemeData(color: AppColors.textPrimary), + dividerTheme: const DividerThemeData( + color: AppColors.border, + thickness: 1, + ), + switchTheme: SwitchThemeData( + thumbColor: MaterialStateProperty.resolveWith((states) { + if (states.contains(MaterialState.selected)) return AppColors.primary; + return AppColors.textSecondary; + }), + trackColor: MaterialStateProperty.resolveWith((states) { + if (states.contains(MaterialState.selected)) { + return AppColors.primary.withOpacity(0.4); + } + return AppColors.border; + }), + ), + ); + } + + static ThemeData get highContrastTheme => HighContrastTheme.theme; + + static ThemeData get lightTheme { + const colorScheme = ColorScheme.light( + primary: AppColors.primary, + secondary: AppColors.secondary, + error: AppColors.error, + ); + + return ThemeData( + useMaterial3: true, + colorScheme: colorScheme, + cardTheme: const CardThemeData(elevation: 2), + appBarTheme: const AppBarTheme(elevation: 0), + inputDecorationTheme: InputDecorationTheme( + filled: true, + border: OutlineInputBorder( + borderRadius: BorderRadius.circular(8), + ), + enabledBorder: OutlineInputBorder( + borderRadius: BorderRadius.circular(8), + ), + focusedBorder: OutlineInputBorder( + borderRadius: BorderRadius.circular(8), + borderSide: const BorderSide(color: AppColors.primary), + ), + ), + ); + } +} diff --git a/apps/mobile/lib/core/models/agent_models.dart b/apps/mobile/lib/core/models/agent_models.dart new file mode 100644 index 0000000..7e0a823 --- /dev/null +++ b/apps/mobile/lib/core/models/agent_models.dart @@ -0,0 +1,27 @@ +import 'package:freezed_annotation/freezed_annotation.dart'; + +part 'agent_models.freezed.dart'; +part 'agent_models.g.dart'; + +enum AgentType { claudeCode, openCode, aider, goose, custom } + +enum AgentConnectionStatus { connected, disconnected, inactive } + +@freezed +class AgentConfig with _$AgentConfig { + const factory AgentConfig({ + required String id, + required String displayName, + required AgentType type, + required String bridgeUrl, + required String authToken, + String? workingDirectory, + @Default(AgentConnectionStatus.disconnected) AgentConnectionStatus status, + DateTime? lastConnectedAt, + required DateTime createdAt, + required DateTime updatedAt, + }) = _AgentConfig; + + factory AgentConfig.fromJson(Map json) => + _$AgentConfigFromJson(json); +} diff --git a/apps/mobile/lib/core/models/agent_models.freezed.dart b/apps/mobile/lib/core/models/agent_models.freezed.dart new file mode 100644 index 0000000..4b69590 --- /dev/null +++ b/apps/mobile/lib/core/models/agent_models.freezed.dart @@ -0,0 +1,367 @@ +// coverage:ignore-file +// GENERATED CODE - DO NOT MODIFY BY HAND +// ignore_for_file: type=lint +// ignore_for_file: unused_element, deprecated_member_use, deprecated_member_use_from_same_package, use_function_type_syntax_for_parameters, unnecessary_const, avoid_init_to_null, invalid_override_different_default_values_named, prefer_expression_function_bodies, annotate_overrides, invalid_annotation_target, unnecessary_question_mark + +part of 'agent_models.dart'; + +// ************************************************************************** +// FreezedGenerator +// ************************************************************************** + +T _$identity(T value) => value; + +final _privateConstructorUsedError = UnsupportedError( + 'It seems like you constructed your class using `MyClass._()`. This constructor is only meant to be used by freezed and you are not supposed to need it nor use it.\nPlease check the documentation here for more information: https://github.com/rrousselGit/freezed#adding-getters-and-methods-to-our-models'); + +AgentConfig _$AgentConfigFromJson(Map json) { + return _AgentConfig.fromJson(json); +} + +/// @nodoc +mixin _$AgentConfig { + String get id => throw _privateConstructorUsedError; + String get displayName => throw _privateConstructorUsedError; + AgentType get type => throw _privateConstructorUsedError; + String get bridgeUrl => throw _privateConstructorUsedError; + String get authToken => throw _privateConstructorUsedError; + String? get workingDirectory => throw _privateConstructorUsedError; + AgentConnectionStatus get status => throw _privateConstructorUsedError; + DateTime? get lastConnectedAt => throw _privateConstructorUsedError; + DateTime get createdAt => throw _privateConstructorUsedError; + DateTime get updatedAt => throw _privateConstructorUsedError; + + /// Serializes this AgentConfig to a JSON map. + Map toJson() => throw _privateConstructorUsedError; + + /// Create a copy of AgentConfig + /// with the given fields replaced by the non-null parameter values. + @JsonKey(includeFromJson: false, includeToJson: false) + $AgentConfigCopyWith get copyWith => + throw _privateConstructorUsedError; +} + +/// @nodoc +abstract class $AgentConfigCopyWith<$Res> { + factory $AgentConfigCopyWith( + AgentConfig value, $Res Function(AgentConfig) then) = + _$AgentConfigCopyWithImpl<$Res, AgentConfig>; + @useResult + $Res call( + {String id, + String displayName, + AgentType type, + String bridgeUrl, + String authToken, + String? workingDirectory, + AgentConnectionStatus status, + DateTime? lastConnectedAt, + DateTime createdAt, + DateTime updatedAt}); +} + +/// @nodoc +class _$AgentConfigCopyWithImpl<$Res, $Val extends AgentConfig> + implements $AgentConfigCopyWith<$Res> { + _$AgentConfigCopyWithImpl(this._value, this._then); + + // ignore: unused_field + final $Val _value; + // ignore: unused_field + final $Res Function($Val) _then; + + /// Create a copy of AgentConfig + /// with the given fields replaced by the non-null parameter values. + @pragma('vm:prefer-inline') + @override + $Res call({ + Object? id = null, + Object? displayName = null, + Object? type = null, + Object? bridgeUrl = null, + Object? authToken = null, + Object? workingDirectory = freezed, + Object? status = null, + Object? lastConnectedAt = freezed, + Object? createdAt = null, + Object? updatedAt = null, + }) { + return _then(_value.copyWith( + id: null == id + ? _value.id + : id // ignore: cast_nullable_to_non_nullable + as String, + displayName: null == displayName + ? _value.displayName + : displayName // ignore: cast_nullable_to_non_nullable + as String, + type: null == type + ? _value.type + : type // ignore: cast_nullable_to_non_nullable + as AgentType, + bridgeUrl: null == bridgeUrl + ? _value.bridgeUrl + : bridgeUrl // ignore: cast_nullable_to_non_nullable + as String, + authToken: null == authToken + ? _value.authToken + : authToken // ignore: cast_nullable_to_non_nullable + as String, + workingDirectory: freezed == workingDirectory + ? _value.workingDirectory + : workingDirectory // ignore: cast_nullable_to_non_nullable + as String?, + status: null == status + ? _value.status + : status // ignore: cast_nullable_to_non_nullable + as AgentConnectionStatus, + lastConnectedAt: freezed == lastConnectedAt + ? _value.lastConnectedAt + : lastConnectedAt // ignore: cast_nullable_to_non_nullable + as DateTime?, + createdAt: null == createdAt + ? _value.createdAt + : createdAt // ignore: cast_nullable_to_non_nullable + as DateTime, + updatedAt: null == updatedAt + ? _value.updatedAt + : updatedAt // ignore: cast_nullable_to_non_nullable + as DateTime, + ) as $Val); + } +} + +/// @nodoc +abstract class _$$AgentConfigImplCopyWith<$Res> + implements $AgentConfigCopyWith<$Res> { + factory _$$AgentConfigImplCopyWith( + _$AgentConfigImpl value, $Res Function(_$AgentConfigImpl) then) = + __$$AgentConfigImplCopyWithImpl<$Res>; + @override + @useResult + $Res call( + {String id, + String displayName, + AgentType type, + String bridgeUrl, + String authToken, + String? workingDirectory, + AgentConnectionStatus status, + DateTime? lastConnectedAt, + DateTime createdAt, + DateTime updatedAt}); +} + +/// @nodoc +class __$$AgentConfigImplCopyWithImpl<$Res> + extends _$AgentConfigCopyWithImpl<$Res, _$AgentConfigImpl> + implements _$$AgentConfigImplCopyWith<$Res> { + __$$AgentConfigImplCopyWithImpl( + _$AgentConfigImpl _value, $Res Function(_$AgentConfigImpl) _then) + : super(_value, _then); + + /// Create a copy of AgentConfig + /// with the given fields replaced by the non-null parameter values. + @pragma('vm:prefer-inline') + @override + $Res call({ + Object? id = null, + Object? displayName = null, + Object? type = null, + Object? bridgeUrl = null, + Object? authToken = null, + Object? workingDirectory = freezed, + Object? status = null, + Object? lastConnectedAt = freezed, + Object? createdAt = null, + Object? updatedAt = null, + }) { + return _then(_$AgentConfigImpl( + id: null == id + ? _value.id + : id // ignore: cast_nullable_to_non_nullable + as String, + displayName: null == displayName + ? _value.displayName + : displayName // ignore: cast_nullable_to_non_nullable + as String, + type: null == type + ? _value.type + : type // ignore: cast_nullable_to_non_nullable + as AgentType, + bridgeUrl: null == bridgeUrl + ? _value.bridgeUrl + : bridgeUrl // ignore: cast_nullable_to_non_nullable + as String, + authToken: null == authToken + ? _value.authToken + : authToken // ignore: cast_nullable_to_non_nullable + as String, + workingDirectory: freezed == workingDirectory + ? _value.workingDirectory + : workingDirectory // ignore: cast_nullable_to_non_nullable + as String?, + status: null == status + ? _value.status + : status // ignore: cast_nullable_to_non_nullable + as AgentConnectionStatus, + lastConnectedAt: freezed == lastConnectedAt + ? _value.lastConnectedAt + : lastConnectedAt // ignore: cast_nullable_to_non_nullable + as DateTime?, + createdAt: null == createdAt + ? _value.createdAt + : createdAt // ignore: cast_nullable_to_non_nullable + as DateTime, + updatedAt: null == updatedAt + ? _value.updatedAt + : updatedAt // ignore: cast_nullable_to_non_nullable + as DateTime, + )); + } +} + +/// @nodoc +@JsonSerializable() +class _$AgentConfigImpl implements _AgentConfig { + const _$AgentConfigImpl( + {required this.id, + required this.displayName, + required this.type, + required this.bridgeUrl, + required this.authToken, + this.workingDirectory, + this.status = AgentConnectionStatus.disconnected, + this.lastConnectedAt, + required this.createdAt, + required this.updatedAt}); + + factory _$AgentConfigImpl.fromJson(Map json) => + _$$AgentConfigImplFromJson(json); + + @override + final String id; + @override + final String displayName; + @override + final AgentType type; + @override + final String bridgeUrl; + @override + final String authToken; + @override + final String? workingDirectory; + @override + @JsonKey() + final AgentConnectionStatus status; + @override + final DateTime? lastConnectedAt; + @override + final DateTime createdAt; + @override + final DateTime updatedAt; + + @override + String toString() { + return 'AgentConfig(id: $id, displayName: $displayName, type: $type, bridgeUrl: $bridgeUrl, authToken: $authToken, workingDirectory: $workingDirectory, status: $status, lastConnectedAt: $lastConnectedAt, createdAt: $createdAt, updatedAt: $updatedAt)'; + } + + @override + bool operator ==(Object other) { + return identical(this, other) || + (other.runtimeType == runtimeType && + other is _$AgentConfigImpl && + (identical(other.id, id) || other.id == id) && + (identical(other.displayName, displayName) || + other.displayName == displayName) && + (identical(other.type, type) || other.type == type) && + (identical(other.bridgeUrl, bridgeUrl) || + other.bridgeUrl == bridgeUrl) && + (identical(other.authToken, authToken) || + other.authToken == authToken) && + (identical(other.workingDirectory, workingDirectory) || + other.workingDirectory == workingDirectory) && + (identical(other.status, status) || other.status == status) && + (identical(other.lastConnectedAt, lastConnectedAt) || + other.lastConnectedAt == lastConnectedAt) && + (identical(other.createdAt, createdAt) || + other.createdAt == createdAt) && + (identical(other.updatedAt, updatedAt) || + other.updatedAt == updatedAt)); + } + + @JsonKey(includeFromJson: false, includeToJson: false) + @override + int get hashCode => Object.hash( + runtimeType, + id, + displayName, + type, + bridgeUrl, + authToken, + workingDirectory, + status, + lastConnectedAt, + createdAt, + updatedAt); + + /// Create a copy of AgentConfig + /// with the given fields replaced by the non-null parameter values. + @JsonKey(includeFromJson: false, includeToJson: false) + @override + @pragma('vm:prefer-inline') + _$$AgentConfigImplCopyWith<_$AgentConfigImpl> get copyWith => + __$$AgentConfigImplCopyWithImpl<_$AgentConfigImpl>(this, _$identity); + + @override + Map toJson() { + return _$$AgentConfigImplToJson( + this, + ); + } +} + +abstract class _AgentConfig implements AgentConfig { + const factory _AgentConfig( + {required final String id, + required final String displayName, + required final AgentType type, + required final String bridgeUrl, + required final String authToken, + final String? workingDirectory, + final AgentConnectionStatus status, + final DateTime? lastConnectedAt, + required final DateTime createdAt, + required final DateTime updatedAt}) = _$AgentConfigImpl; + + factory _AgentConfig.fromJson(Map json) = + _$AgentConfigImpl.fromJson; + + @override + String get id; + @override + String get displayName; + @override + AgentType get type; + @override + String get bridgeUrl; + @override + String get authToken; + @override + String? get workingDirectory; + @override + AgentConnectionStatus get status; + @override + DateTime? get lastConnectedAt; + @override + DateTime get createdAt; + @override + DateTime get updatedAt; + + /// Create a copy of AgentConfig + /// with the given fields replaced by the non-null parameter values. + @override + @JsonKey(includeFromJson: false, includeToJson: false) + _$$AgentConfigImplCopyWith<_$AgentConfigImpl> get copyWith => + throw _privateConstructorUsedError; +} diff --git a/apps/mobile/lib/core/models/agent_models.g.dart b/apps/mobile/lib/core/models/agent_models.g.dart new file mode 100644 index 0000000..0589662 --- /dev/null +++ b/apps/mobile/lib/core/models/agent_models.g.dart @@ -0,0 +1,53 @@ +// GENERATED CODE - DO NOT MODIFY BY HAND + +part of 'agent_models.dart'; + +// ************************************************************************** +// JsonSerializableGenerator +// ************************************************************************** + +_$AgentConfigImpl _$$AgentConfigImplFromJson(Map json) => + _$AgentConfigImpl( + id: json['id'] as String, + displayName: json['displayName'] as String, + type: $enumDecode(_$AgentTypeEnumMap, json['type']), + bridgeUrl: json['bridgeUrl'] as String, + authToken: json['authToken'] as String, + workingDirectory: json['workingDirectory'] as String?, + status: + $enumDecodeNullable(_$AgentConnectionStatusEnumMap, json['status']) ?? + AgentConnectionStatus.disconnected, + lastConnectedAt: json['lastConnectedAt'] == null + ? null + : DateTime.parse(json['lastConnectedAt'] as String), + createdAt: DateTime.parse(json['createdAt'] as String), + updatedAt: DateTime.parse(json['updatedAt'] as String), + ); + +Map _$$AgentConfigImplToJson(_$AgentConfigImpl instance) => + { + 'id': instance.id, + 'displayName': instance.displayName, + 'type': _$AgentTypeEnumMap[instance.type]!, + 'bridgeUrl': instance.bridgeUrl, + 'authToken': instance.authToken, + 'workingDirectory': instance.workingDirectory, + 'status': _$AgentConnectionStatusEnumMap[instance.status]!, + 'lastConnectedAt': instance.lastConnectedAt?.toIso8601String(), + 'createdAt': instance.createdAt.toIso8601String(), + 'updatedAt': instance.updatedAt.toIso8601String(), + }; + +const _$AgentTypeEnumMap = { + AgentType.claudeCode: 'claudeCode', + AgentType.openCode: 'openCode', + AgentType.aider: 'aider', + AgentType.goose: 'goose', + AgentType.custom: 'custom', +}; + +const _$AgentConnectionStatusEnumMap = { + AgentConnectionStatus.connected: 'connected', + AgentConnectionStatus.disconnected: 'disconnected', + AgentConnectionStatus.inactive: 'inactive', +}; diff --git a/apps/mobile/lib/core/models/file_models.dart b/apps/mobile/lib/core/models/file_models.dart new file mode 100644 index 0000000..732cf52 --- /dev/null +++ b/apps/mobile/lib/core/models/file_models.dart @@ -0,0 +1,22 @@ +import 'package:freezed_annotation/freezed_annotation.dart'; + +part 'file_models.freezed.dart'; +part 'file_models.g.dart'; + +enum FileNodeType { file, directory } + +@freezed +class FileTreeNode with _$FileTreeNode { + const factory FileTreeNode({ + required String name, + required String path, + required FileNodeType type, + List? children, + int? size, + DateTime? modifiedAt, + String? content, + }) = _FileTreeNode; + + factory FileTreeNode.fromJson(Map json) => + _$FileTreeNodeFromJson(json); +} diff --git a/apps/mobile/lib/core/models/file_models.freezed.dart b/apps/mobile/lib/core/models/file_models.freezed.dart new file mode 100644 index 0000000..b68bac3 --- /dev/null +++ b/apps/mobile/lib/core/models/file_models.freezed.dart @@ -0,0 +1,306 @@ +// coverage:ignore-file +// GENERATED CODE - DO NOT MODIFY BY HAND +// ignore_for_file: type=lint +// ignore_for_file: unused_element, deprecated_member_use, deprecated_member_use_from_same_package, use_function_type_syntax_for_parameters, unnecessary_const, avoid_init_to_null, invalid_override_different_default_values_named, prefer_expression_function_bodies, annotate_overrides, invalid_annotation_target, unnecessary_question_mark + +part of 'file_models.dart'; + +// ************************************************************************** +// FreezedGenerator +// ************************************************************************** + +T _$identity(T value) => value; + +final _privateConstructorUsedError = UnsupportedError( + 'It seems like you constructed your class using `MyClass._()`. This constructor is only meant to be used by freezed and you are not supposed to need it nor use it.\nPlease check the documentation here for more information: https://github.com/rrousselGit/freezed#adding-getters-and-methods-to-our-models'); + +FileTreeNode _$FileTreeNodeFromJson(Map json) { + return _FileTreeNode.fromJson(json); +} + +/// @nodoc +mixin _$FileTreeNode { + String get name => throw _privateConstructorUsedError; + String get path => throw _privateConstructorUsedError; + FileNodeType get type => throw _privateConstructorUsedError; + List? get children => throw _privateConstructorUsedError; + int? get size => throw _privateConstructorUsedError; + DateTime? get modifiedAt => throw _privateConstructorUsedError; + String? get content => throw _privateConstructorUsedError; + + /// Serializes this FileTreeNode to a JSON map. + Map toJson() => throw _privateConstructorUsedError; + + /// Create a copy of FileTreeNode + /// with the given fields replaced by the non-null parameter values. + @JsonKey(includeFromJson: false, includeToJson: false) + $FileTreeNodeCopyWith get copyWith => + throw _privateConstructorUsedError; +} + +/// @nodoc +abstract class $FileTreeNodeCopyWith<$Res> { + factory $FileTreeNodeCopyWith( + FileTreeNode value, $Res Function(FileTreeNode) then) = + _$FileTreeNodeCopyWithImpl<$Res, FileTreeNode>; + @useResult + $Res call( + {String name, + String path, + FileNodeType type, + List? children, + int? size, + DateTime? modifiedAt, + String? content}); +} + +/// @nodoc +class _$FileTreeNodeCopyWithImpl<$Res, $Val extends FileTreeNode> + implements $FileTreeNodeCopyWith<$Res> { + _$FileTreeNodeCopyWithImpl(this._value, this._then); + + // ignore: unused_field + final $Val _value; + // ignore: unused_field + final $Res Function($Val) _then; + + /// Create a copy of FileTreeNode + /// with the given fields replaced by the non-null parameter values. + @pragma('vm:prefer-inline') + @override + $Res call({ + Object? name = null, + Object? path = null, + Object? type = null, + Object? children = freezed, + Object? size = freezed, + Object? modifiedAt = freezed, + Object? content = freezed, + }) { + return _then(_value.copyWith( + name: null == name + ? _value.name + : name // ignore: cast_nullable_to_non_nullable + as String, + path: null == path + ? _value.path + : path // ignore: cast_nullable_to_non_nullable + as String, + type: null == type + ? _value.type + : type // ignore: cast_nullable_to_non_nullable + as FileNodeType, + children: freezed == children + ? _value.children + : children // ignore: cast_nullable_to_non_nullable + as List?, + size: freezed == size + ? _value.size + : size // ignore: cast_nullable_to_non_nullable + as int?, + modifiedAt: freezed == modifiedAt + ? _value.modifiedAt + : modifiedAt // ignore: cast_nullable_to_non_nullable + as DateTime?, + content: freezed == content + ? _value.content + : content // ignore: cast_nullable_to_non_nullable + as String?, + ) as $Val); + } +} + +/// @nodoc +abstract class _$$FileTreeNodeImplCopyWith<$Res> + implements $FileTreeNodeCopyWith<$Res> { + factory _$$FileTreeNodeImplCopyWith( + _$FileTreeNodeImpl value, $Res Function(_$FileTreeNodeImpl) then) = + __$$FileTreeNodeImplCopyWithImpl<$Res>; + @override + @useResult + $Res call( + {String name, + String path, + FileNodeType type, + List? children, + int? size, + DateTime? modifiedAt, + String? content}); +} + +/// @nodoc +class __$$FileTreeNodeImplCopyWithImpl<$Res> + extends _$FileTreeNodeCopyWithImpl<$Res, _$FileTreeNodeImpl> + implements _$$FileTreeNodeImplCopyWith<$Res> { + __$$FileTreeNodeImplCopyWithImpl( + _$FileTreeNodeImpl _value, $Res Function(_$FileTreeNodeImpl) _then) + : super(_value, _then); + + /// Create a copy of FileTreeNode + /// with the given fields replaced by the non-null parameter values. + @pragma('vm:prefer-inline') + @override + $Res call({ + Object? name = null, + Object? path = null, + Object? type = null, + Object? children = freezed, + Object? size = freezed, + Object? modifiedAt = freezed, + Object? content = freezed, + }) { + return _then(_$FileTreeNodeImpl( + name: null == name + ? _value.name + : name // ignore: cast_nullable_to_non_nullable + as String, + path: null == path + ? _value.path + : path // ignore: cast_nullable_to_non_nullable + as String, + type: null == type + ? _value.type + : type // ignore: cast_nullable_to_non_nullable + as FileNodeType, + children: freezed == children + ? _value._children + : children // ignore: cast_nullable_to_non_nullable + as List?, + size: freezed == size + ? _value.size + : size // ignore: cast_nullable_to_non_nullable + as int?, + modifiedAt: freezed == modifiedAt + ? _value.modifiedAt + : modifiedAt // ignore: cast_nullable_to_non_nullable + as DateTime?, + content: freezed == content + ? _value.content + : content // ignore: cast_nullable_to_non_nullable + as String?, + )); + } +} + +/// @nodoc +@JsonSerializable() +class _$FileTreeNodeImpl implements _FileTreeNode { + const _$FileTreeNodeImpl( + {required this.name, + required this.path, + required this.type, + final List? children, + this.size, + this.modifiedAt, + this.content}) + : _children = children; + + factory _$FileTreeNodeImpl.fromJson(Map json) => + _$$FileTreeNodeImplFromJson(json); + + @override + final String name; + @override + final String path; + @override + final FileNodeType type; + final List? _children; + @override + List? get children { + final value = _children; + if (value == null) return null; + if (_children is EqualUnmodifiableListView) return _children; + // ignore: implicit_dynamic_type + return EqualUnmodifiableListView(value); + } + + @override + final int? size; + @override + final DateTime? modifiedAt; + @override + final String? content; + + @override + String toString() { + return 'FileTreeNode(name: $name, path: $path, type: $type, children: $children, size: $size, modifiedAt: $modifiedAt, content: $content)'; + } + + @override + bool operator ==(Object other) { + return identical(this, other) || + (other.runtimeType == runtimeType && + other is _$FileTreeNodeImpl && + (identical(other.name, name) || other.name == name) && + (identical(other.path, path) || other.path == path) && + (identical(other.type, type) || other.type == type) && + const DeepCollectionEquality().equals(other._children, _children) && + (identical(other.size, size) || other.size == size) && + (identical(other.modifiedAt, modifiedAt) || + other.modifiedAt == modifiedAt) && + (identical(other.content, content) || other.content == content)); + } + + @JsonKey(includeFromJson: false, includeToJson: false) + @override + int get hashCode => Object.hash( + runtimeType, + name, + path, + type, + const DeepCollectionEquality().hash(_children), + size, + modifiedAt, + content); + + /// Create a copy of FileTreeNode + /// with the given fields replaced by the non-null parameter values. + @JsonKey(includeFromJson: false, includeToJson: false) + @override + @pragma('vm:prefer-inline') + _$$FileTreeNodeImplCopyWith<_$FileTreeNodeImpl> get copyWith => + __$$FileTreeNodeImplCopyWithImpl<_$FileTreeNodeImpl>(this, _$identity); + + @override + Map toJson() { + return _$$FileTreeNodeImplToJson( + this, + ); + } +} + +abstract class _FileTreeNode implements FileTreeNode { + const factory _FileTreeNode( + {required final String name, + required final String path, + required final FileNodeType type, + final List? children, + final int? size, + final DateTime? modifiedAt, + final String? content}) = _$FileTreeNodeImpl; + + factory _FileTreeNode.fromJson(Map json) = + _$FileTreeNodeImpl.fromJson; + + @override + String get name; + @override + String get path; + @override + FileNodeType get type; + @override + List? get children; + @override + int? get size; + @override + DateTime? get modifiedAt; + @override + String? get content; + + /// Create a copy of FileTreeNode + /// with the given fields replaced by the non-null parameter values. + @override + @JsonKey(includeFromJson: false, includeToJson: false) + _$$FileTreeNodeImplCopyWith<_$FileTreeNodeImpl> get copyWith => + throw _privateConstructorUsedError; +} diff --git a/apps/mobile/lib/core/models/file_models.g.dart b/apps/mobile/lib/core/models/file_models.g.dart new file mode 100644 index 0000000..d85d2ec --- /dev/null +++ b/apps/mobile/lib/core/models/file_models.g.dart @@ -0,0 +1,38 @@ +// GENERATED CODE - DO NOT MODIFY BY HAND + +part of 'file_models.dart'; + +// ************************************************************************** +// JsonSerializableGenerator +// ************************************************************************** + +_$FileTreeNodeImpl _$$FileTreeNodeImplFromJson(Map json) => + _$FileTreeNodeImpl( + name: json['name'] as String, + path: json['path'] as String, + type: $enumDecode(_$FileNodeTypeEnumMap, json['type']), + children: (json['children'] as List?) + ?.map((e) => FileTreeNode.fromJson(e as Map)) + .toList(), + size: (json['size'] as num?)?.toInt(), + modifiedAt: json['modifiedAt'] == null + ? null + : DateTime.parse(json['modifiedAt'] as String), + content: json['content'] as String?, + ); + +Map _$$FileTreeNodeImplToJson(_$FileTreeNodeImpl instance) => + { + 'name': instance.name, + 'path': instance.path, + 'type': _$FileNodeTypeEnumMap[instance.type]!, + 'children': instance.children, + 'size': instance.size, + 'modifiedAt': instance.modifiedAt?.toIso8601String(), + 'content': instance.content, + }; + +const _$FileNodeTypeEnumMap = { + FileNodeType.file: 'file', + FileNodeType.directory: 'directory', +}; diff --git a/apps/mobile/lib/core/models/git_models.dart b/apps/mobile/lib/core/models/git_models.dart new file mode 100644 index 0000000..17a66da --- /dev/null +++ b/apps/mobile/lib/core/models/git_models.dart @@ -0,0 +1,96 @@ +import 'package:freezed_annotation/freezed_annotation.dart'; + +part 'git_models.freezed.dart'; +part 'git_models.g.dart'; + +enum FileChangeStatus { modified, added, deleted, untracked, renamed } + +enum DiffLineType { context, added, removed } + +@freezed +class GitStatus with _$GitStatus { + const factory GitStatus({ + required String branch, + required List changes, + required int ahead, + required int behind, + required bool isClean, + }) = _GitStatus; + + factory GitStatus.fromJson(Map json) => + _$GitStatusFromJson(json); +} + +@freezed +class GitFileChange with _$GitFileChange { + const factory GitFileChange({ + required String path, + required FileChangeStatus status, + int? additions, + int? deletions, + String? diff, + }) = _GitFileChange; + + factory GitFileChange.fromJson(Map json) => + _$GitFileChangeFromJson(json); +} + +@freezed +class GitBranch with _$GitBranch { + const factory GitBranch({ + required String name, + required bool isCurrent, + String? upstream, + int? ahead, + int? behind, + }) = _GitBranch; + + factory GitBranch.fromJson(Map json) => + _$GitBranchFromJson(json); +} + +@freezed +class DiffFile with _$DiffFile { + const factory DiffFile({ + required String path, + required String oldPath, + required String newPath, + required FileChangeStatus status, + required int additions, + required int deletions, + required List hunks, + String? oldMode, + String? newMode, + }) = _DiffFile; + + factory DiffFile.fromJson(Map json) => + _$DiffFileFromJson(json); +} + +@freezed +class DiffHunk with _$DiffHunk { + const factory DiffHunk({ + required String header, + required int oldStart, + required int oldLines, + required int newStart, + required int newLines, + required List lines, + }) = _DiffHunk; + + factory DiffHunk.fromJson(Map json) => + _$DiffHunkFromJson(json); +} + +@freezed +class DiffLine with _$DiffLine { + const factory DiffLine({ + required DiffLineType type, + required String content, + int? oldLineNumber, + int? newLineNumber, + }) = _DiffLine; + + factory DiffLine.fromJson(Map json) => + _$DiffLineFromJson(json); +} diff --git a/apps/mobile/lib/core/models/git_models.freezed.dart b/apps/mobile/lib/core/models/git_models.freezed.dart new file mode 100644 index 0000000..50d1d10 --- /dev/null +++ b/apps/mobile/lib/core/models/git_models.freezed.dart @@ -0,0 +1,1527 @@ +// coverage:ignore-file +// GENERATED CODE - DO NOT MODIFY BY HAND +// ignore_for_file: type=lint +// ignore_for_file: unused_element, deprecated_member_use, deprecated_member_use_from_same_package, use_function_type_syntax_for_parameters, unnecessary_const, avoid_init_to_null, invalid_override_different_default_values_named, prefer_expression_function_bodies, annotate_overrides, invalid_annotation_target, unnecessary_question_mark + +part of 'git_models.dart'; + +// ************************************************************************** +// FreezedGenerator +// ************************************************************************** + +T _$identity(T value) => value; + +final _privateConstructorUsedError = UnsupportedError( + 'It seems like you constructed your class using `MyClass._()`. This constructor is only meant to be used by freezed and you are not supposed to need it nor use it.\nPlease check the documentation here for more information: https://github.com/rrousselGit/freezed#adding-getters-and-methods-to-our-models'); + +GitStatus _$GitStatusFromJson(Map json) { + return _GitStatus.fromJson(json); +} + +/// @nodoc +mixin _$GitStatus { + String get branch => throw _privateConstructorUsedError; + List get changes => throw _privateConstructorUsedError; + int get ahead => throw _privateConstructorUsedError; + int get behind => throw _privateConstructorUsedError; + bool get isClean => throw _privateConstructorUsedError; + + /// Serializes this GitStatus to a JSON map. + Map toJson() => throw _privateConstructorUsedError; + + /// Create a copy of GitStatus + /// with the given fields replaced by the non-null parameter values. + @JsonKey(includeFromJson: false, includeToJson: false) + $GitStatusCopyWith get copyWith => + throw _privateConstructorUsedError; +} + +/// @nodoc +abstract class $GitStatusCopyWith<$Res> { + factory $GitStatusCopyWith(GitStatus value, $Res Function(GitStatus) then) = + _$GitStatusCopyWithImpl<$Res, GitStatus>; + @useResult + $Res call( + {String branch, + List changes, + int ahead, + int behind, + bool isClean}); +} + +/// @nodoc +class _$GitStatusCopyWithImpl<$Res, $Val extends GitStatus> + implements $GitStatusCopyWith<$Res> { + _$GitStatusCopyWithImpl(this._value, this._then); + + // ignore: unused_field + final $Val _value; + // ignore: unused_field + final $Res Function($Val) _then; + + /// Create a copy of GitStatus + /// with the given fields replaced by the non-null parameter values. + @pragma('vm:prefer-inline') + @override + $Res call({ + Object? branch = null, + Object? changes = null, + Object? ahead = null, + Object? behind = null, + Object? isClean = null, + }) { + return _then(_value.copyWith( + branch: null == branch + ? _value.branch + : branch // ignore: cast_nullable_to_non_nullable + as String, + changes: null == changes + ? _value.changes + : changes // ignore: cast_nullable_to_non_nullable + as List, + ahead: null == ahead + ? _value.ahead + : ahead // ignore: cast_nullable_to_non_nullable + as int, + behind: null == behind + ? _value.behind + : behind // ignore: cast_nullable_to_non_nullable + as int, + isClean: null == isClean + ? _value.isClean + : isClean // ignore: cast_nullable_to_non_nullable + as bool, + ) as $Val); + } +} + +/// @nodoc +abstract class _$$GitStatusImplCopyWith<$Res> + implements $GitStatusCopyWith<$Res> { + factory _$$GitStatusImplCopyWith( + _$GitStatusImpl value, $Res Function(_$GitStatusImpl) then) = + __$$GitStatusImplCopyWithImpl<$Res>; + @override + @useResult + $Res call( + {String branch, + List changes, + int ahead, + int behind, + bool isClean}); +} + +/// @nodoc +class __$$GitStatusImplCopyWithImpl<$Res> + extends _$GitStatusCopyWithImpl<$Res, _$GitStatusImpl> + implements _$$GitStatusImplCopyWith<$Res> { + __$$GitStatusImplCopyWithImpl( + _$GitStatusImpl _value, $Res Function(_$GitStatusImpl) _then) + : super(_value, _then); + + /// Create a copy of GitStatus + /// with the given fields replaced by the non-null parameter values. + @pragma('vm:prefer-inline') + @override + $Res call({ + Object? branch = null, + Object? changes = null, + Object? ahead = null, + Object? behind = null, + Object? isClean = null, + }) { + return _then(_$GitStatusImpl( + branch: null == branch + ? _value.branch + : branch // ignore: cast_nullable_to_non_nullable + as String, + changes: null == changes + ? _value._changes + : changes // ignore: cast_nullable_to_non_nullable + as List, + ahead: null == ahead + ? _value.ahead + : ahead // ignore: cast_nullable_to_non_nullable + as int, + behind: null == behind + ? _value.behind + : behind // ignore: cast_nullable_to_non_nullable + as int, + isClean: null == isClean + ? _value.isClean + : isClean // ignore: cast_nullable_to_non_nullable + as bool, + )); + } +} + +/// @nodoc +@JsonSerializable() +class _$GitStatusImpl implements _GitStatus { + const _$GitStatusImpl( + {required this.branch, + required final List changes, + required this.ahead, + required this.behind, + required this.isClean}) + : _changes = changes; + + factory _$GitStatusImpl.fromJson(Map json) => + _$$GitStatusImplFromJson(json); + + @override + final String branch; + final List _changes; + @override + List get changes { + if (_changes is EqualUnmodifiableListView) return _changes; + // ignore: implicit_dynamic_type + return EqualUnmodifiableListView(_changes); + } + + @override + final int ahead; + @override + final int behind; + @override + final bool isClean; + + @override + String toString() { + return 'GitStatus(branch: $branch, changes: $changes, ahead: $ahead, behind: $behind, isClean: $isClean)'; + } + + @override + bool operator ==(Object other) { + return identical(this, other) || + (other.runtimeType == runtimeType && + other is _$GitStatusImpl && + (identical(other.branch, branch) || other.branch == branch) && + const DeepCollectionEquality().equals(other._changes, _changes) && + (identical(other.ahead, ahead) || other.ahead == ahead) && + (identical(other.behind, behind) || other.behind == behind) && + (identical(other.isClean, isClean) || other.isClean == isClean)); + } + + @JsonKey(includeFromJson: false, includeToJson: false) + @override + int get hashCode => Object.hash(runtimeType, branch, + const DeepCollectionEquality().hash(_changes), ahead, behind, isClean); + + /// Create a copy of GitStatus + /// with the given fields replaced by the non-null parameter values. + @JsonKey(includeFromJson: false, includeToJson: false) + @override + @pragma('vm:prefer-inline') + _$$GitStatusImplCopyWith<_$GitStatusImpl> get copyWith => + __$$GitStatusImplCopyWithImpl<_$GitStatusImpl>(this, _$identity); + + @override + Map toJson() { + return _$$GitStatusImplToJson( + this, + ); + } +} + +abstract class _GitStatus implements GitStatus { + const factory _GitStatus( + {required final String branch, + required final List changes, + required final int ahead, + required final int behind, + required final bool isClean}) = _$GitStatusImpl; + + factory _GitStatus.fromJson(Map json) = + _$GitStatusImpl.fromJson; + + @override + String get branch; + @override + List get changes; + @override + int get ahead; + @override + int get behind; + @override + bool get isClean; + + /// Create a copy of GitStatus + /// with the given fields replaced by the non-null parameter values. + @override + @JsonKey(includeFromJson: false, includeToJson: false) + _$$GitStatusImplCopyWith<_$GitStatusImpl> get copyWith => + throw _privateConstructorUsedError; +} + +GitFileChange _$GitFileChangeFromJson(Map json) { + return _GitFileChange.fromJson(json); +} + +/// @nodoc +mixin _$GitFileChange { + String get path => throw _privateConstructorUsedError; + FileChangeStatus get status => throw _privateConstructorUsedError; + int? get additions => throw _privateConstructorUsedError; + int? get deletions => throw _privateConstructorUsedError; + String? get diff => throw _privateConstructorUsedError; + + /// Serializes this GitFileChange to a JSON map. + Map toJson() => throw _privateConstructorUsedError; + + /// Create a copy of GitFileChange + /// with the given fields replaced by the non-null parameter values. + @JsonKey(includeFromJson: false, includeToJson: false) + $GitFileChangeCopyWith get copyWith => + throw _privateConstructorUsedError; +} + +/// @nodoc +abstract class $GitFileChangeCopyWith<$Res> { + factory $GitFileChangeCopyWith( + GitFileChange value, $Res Function(GitFileChange) then) = + _$GitFileChangeCopyWithImpl<$Res, GitFileChange>; + @useResult + $Res call( + {String path, + FileChangeStatus status, + int? additions, + int? deletions, + String? diff}); +} + +/// @nodoc +class _$GitFileChangeCopyWithImpl<$Res, $Val extends GitFileChange> + implements $GitFileChangeCopyWith<$Res> { + _$GitFileChangeCopyWithImpl(this._value, this._then); + + // ignore: unused_field + final $Val _value; + // ignore: unused_field + final $Res Function($Val) _then; + + /// Create a copy of GitFileChange + /// with the given fields replaced by the non-null parameter values. + @pragma('vm:prefer-inline') + @override + $Res call({ + Object? path = null, + Object? status = null, + Object? additions = freezed, + Object? deletions = freezed, + Object? diff = freezed, + }) { + return _then(_value.copyWith( + path: null == path + ? _value.path + : path // ignore: cast_nullable_to_non_nullable + as String, + status: null == status + ? _value.status + : status // ignore: cast_nullable_to_non_nullable + as FileChangeStatus, + additions: freezed == additions + ? _value.additions + : additions // ignore: cast_nullable_to_non_nullable + as int?, + deletions: freezed == deletions + ? _value.deletions + : deletions // ignore: cast_nullable_to_non_nullable + as int?, + diff: freezed == diff + ? _value.diff + : diff // ignore: cast_nullable_to_non_nullable + as String?, + ) as $Val); + } +} + +/// @nodoc +abstract class _$$GitFileChangeImplCopyWith<$Res> + implements $GitFileChangeCopyWith<$Res> { + factory _$$GitFileChangeImplCopyWith( + _$GitFileChangeImpl value, $Res Function(_$GitFileChangeImpl) then) = + __$$GitFileChangeImplCopyWithImpl<$Res>; + @override + @useResult + $Res call( + {String path, + FileChangeStatus status, + int? additions, + int? deletions, + String? diff}); +} + +/// @nodoc +class __$$GitFileChangeImplCopyWithImpl<$Res> + extends _$GitFileChangeCopyWithImpl<$Res, _$GitFileChangeImpl> + implements _$$GitFileChangeImplCopyWith<$Res> { + __$$GitFileChangeImplCopyWithImpl( + _$GitFileChangeImpl _value, $Res Function(_$GitFileChangeImpl) _then) + : super(_value, _then); + + /// Create a copy of GitFileChange + /// with the given fields replaced by the non-null parameter values. + @pragma('vm:prefer-inline') + @override + $Res call({ + Object? path = null, + Object? status = null, + Object? additions = freezed, + Object? deletions = freezed, + Object? diff = freezed, + }) { + return _then(_$GitFileChangeImpl( + path: null == path + ? _value.path + : path // ignore: cast_nullable_to_non_nullable + as String, + status: null == status + ? _value.status + : status // ignore: cast_nullable_to_non_nullable + as FileChangeStatus, + additions: freezed == additions + ? _value.additions + : additions // ignore: cast_nullable_to_non_nullable + as int?, + deletions: freezed == deletions + ? _value.deletions + : deletions // ignore: cast_nullable_to_non_nullable + as int?, + diff: freezed == diff + ? _value.diff + : diff // ignore: cast_nullable_to_non_nullable + as String?, + )); + } +} + +/// @nodoc +@JsonSerializable() +class _$GitFileChangeImpl implements _GitFileChange { + const _$GitFileChangeImpl( + {required this.path, + required this.status, + this.additions, + this.deletions, + this.diff}); + + factory _$GitFileChangeImpl.fromJson(Map json) => + _$$GitFileChangeImplFromJson(json); + + @override + final String path; + @override + final FileChangeStatus status; + @override + final int? additions; + @override + final int? deletions; + @override + final String? diff; + + @override + String toString() { + return 'GitFileChange(path: $path, status: $status, additions: $additions, deletions: $deletions, diff: $diff)'; + } + + @override + bool operator ==(Object other) { + return identical(this, other) || + (other.runtimeType == runtimeType && + other is _$GitFileChangeImpl && + (identical(other.path, path) || other.path == path) && + (identical(other.status, status) || other.status == status) && + (identical(other.additions, additions) || + other.additions == additions) && + (identical(other.deletions, deletions) || + other.deletions == deletions) && + (identical(other.diff, diff) || other.diff == diff)); + } + + @JsonKey(includeFromJson: false, includeToJson: false) + @override + int get hashCode => + Object.hash(runtimeType, path, status, additions, deletions, diff); + + /// Create a copy of GitFileChange + /// with the given fields replaced by the non-null parameter values. + @JsonKey(includeFromJson: false, includeToJson: false) + @override + @pragma('vm:prefer-inline') + _$$GitFileChangeImplCopyWith<_$GitFileChangeImpl> get copyWith => + __$$GitFileChangeImplCopyWithImpl<_$GitFileChangeImpl>(this, _$identity); + + @override + Map toJson() { + return _$$GitFileChangeImplToJson( + this, + ); + } +} + +abstract class _GitFileChange implements GitFileChange { + const factory _GitFileChange( + {required final String path, + required final FileChangeStatus status, + final int? additions, + final int? deletions, + final String? diff}) = _$GitFileChangeImpl; + + factory _GitFileChange.fromJson(Map json) = + _$GitFileChangeImpl.fromJson; + + @override + String get path; + @override + FileChangeStatus get status; + @override + int? get additions; + @override + int? get deletions; + @override + String? get diff; + + /// Create a copy of GitFileChange + /// with the given fields replaced by the non-null parameter values. + @override + @JsonKey(includeFromJson: false, includeToJson: false) + _$$GitFileChangeImplCopyWith<_$GitFileChangeImpl> get copyWith => + throw _privateConstructorUsedError; +} + +GitBranch _$GitBranchFromJson(Map json) { + return _GitBranch.fromJson(json); +} + +/// @nodoc +mixin _$GitBranch { + String get name => throw _privateConstructorUsedError; + bool get isCurrent => throw _privateConstructorUsedError; + String? get upstream => throw _privateConstructorUsedError; + int? get ahead => throw _privateConstructorUsedError; + int? get behind => throw _privateConstructorUsedError; + + /// Serializes this GitBranch to a JSON map. + Map toJson() => throw _privateConstructorUsedError; + + /// Create a copy of GitBranch + /// with the given fields replaced by the non-null parameter values. + @JsonKey(includeFromJson: false, includeToJson: false) + $GitBranchCopyWith get copyWith => + throw _privateConstructorUsedError; +} + +/// @nodoc +abstract class $GitBranchCopyWith<$Res> { + factory $GitBranchCopyWith(GitBranch value, $Res Function(GitBranch) then) = + _$GitBranchCopyWithImpl<$Res, GitBranch>; + @useResult + $Res call( + {String name, bool isCurrent, String? upstream, int? ahead, int? behind}); +} + +/// @nodoc +class _$GitBranchCopyWithImpl<$Res, $Val extends GitBranch> + implements $GitBranchCopyWith<$Res> { + _$GitBranchCopyWithImpl(this._value, this._then); + + // ignore: unused_field + final $Val _value; + // ignore: unused_field + final $Res Function($Val) _then; + + /// Create a copy of GitBranch + /// with the given fields replaced by the non-null parameter values. + @pragma('vm:prefer-inline') + @override + $Res call({ + Object? name = null, + Object? isCurrent = null, + Object? upstream = freezed, + Object? ahead = freezed, + Object? behind = freezed, + }) { + return _then(_value.copyWith( + name: null == name + ? _value.name + : name // ignore: cast_nullable_to_non_nullable + as String, + isCurrent: null == isCurrent + ? _value.isCurrent + : isCurrent // ignore: cast_nullable_to_non_nullable + as bool, + upstream: freezed == upstream + ? _value.upstream + : upstream // ignore: cast_nullable_to_non_nullable + as String?, + ahead: freezed == ahead + ? _value.ahead + : ahead // ignore: cast_nullable_to_non_nullable + as int?, + behind: freezed == behind + ? _value.behind + : behind // ignore: cast_nullable_to_non_nullable + as int?, + ) as $Val); + } +} + +/// @nodoc +abstract class _$$GitBranchImplCopyWith<$Res> + implements $GitBranchCopyWith<$Res> { + factory _$$GitBranchImplCopyWith( + _$GitBranchImpl value, $Res Function(_$GitBranchImpl) then) = + __$$GitBranchImplCopyWithImpl<$Res>; + @override + @useResult + $Res call( + {String name, bool isCurrent, String? upstream, int? ahead, int? behind}); +} + +/// @nodoc +class __$$GitBranchImplCopyWithImpl<$Res> + extends _$GitBranchCopyWithImpl<$Res, _$GitBranchImpl> + implements _$$GitBranchImplCopyWith<$Res> { + __$$GitBranchImplCopyWithImpl( + _$GitBranchImpl _value, $Res Function(_$GitBranchImpl) _then) + : super(_value, _then); + + /// Create a copy of GitBranch + /// with the given fields replaced by the non-null parameter values. + @pragma('vm:prefer-inline') + @override + $Res call({ + Object? name = null, + Object? isCurrent = null, + Object? upstream = freezed, + Object? ahead = freezed, + Object? behind = freezed, + }) { + return _then(_$GitBranchImpl( + name: null == name + ? _value.name + : name // ignore: cast_nullable_to_non_nullable + as String, + isCurrent: null == isCurrent + ? _value.isCurrent + : isCurrent // ignore: cast_nullable_to_non_nullable + as bool, + upstream: freezed == upstream + ? _value.upstream + : upstream // ignore: cast_nullable_to_non_nullable + as String?, + ahead: freezed == ahead + ? _value.ahead + : ahead // ignore: cast_nullable_to_non_nullable + as int?, + behind: freezed == behind + ? _value.behind + : behind // ignore: cast_nullable_to_non_nullable + as int?, + )); + } +} + +/// @nodoc +@JsonSerializable() +class _$GitBranchImpl implements _GitBranch { + const _$GitBranchImpl( + {required this.name, + required this.isCurrent, + this.upstream, + this.ahead, + this.behind}); + + factory _$GitBranchImpl.fromJson(Map json) => + _$$GitBranchImplFromJson(json); + + @override + final String name; + @override + final bool isCurrent; + @override + final String? upstream; + @override + final int? ahead; + @override + final int? behind; + + @override + String toString() { + return 'GitBranch(name: $name, isCurrent: $isCurrent, upstream: $upstream, ahead: $ahead, behind: $behind)'; + } + + @override + bool operator ==(Object other) { + return identical(this, other) || + (other.runtimeType == runtimeType && + other is _$GitBranchImpl && + (identical(other.name, name) || other.name == name) && + (identical(other.isCurrent, isCurrent) || + other.isCurrent == isCurrent) && + (identical(other.upstream, upstream) || + other.upstream == upstream) && + (identical(other.ahead, ahead) || other.ahead == ahead) && + (identical(other.behind, behind) || other.behind == behind)); + } + + @JsonKey(includeFromJson: false, includeToJson: false) + @override + int get hashCode => + Object.hash(runtimeType, name, isCurrent, upstream, ahead, behind); + + /// Create a copy of GitBranch + /// with the given fields replaced by the non-null parameter values. + @JsonKey(includeFromJson: false, includeToJson: false) + @override + @pragma('vm:prefer-inline') + _$$GitBranchImplCopyWith<_$GitBranchImpl> get copyWith => + __$$GitBranchImplCopyWithImpl<_$GitBranchImpl>(this, _$identity); + + @override + Map toJson() { + return _$$GitBranchImplToJson( + this, + ); + } +} + +abstract class _GitBranch implements GitBranch { + const factory _GitBranch( + {required final String name, + required final bool isCurrent, + final String? upstream, + final int? ahead, + final int? behind}) = _$GitBranchImpl; + + factory _GitBranch.fromJson(Map json) = + _$GitBranchImpl.fromJson; + + @override + String get name; + @override + bool get isCurrent; + @override + String? get upstream; + @override + int? get ahead; + @override + int? get behind; + + /// Create a copy of GitBranch + /// with the given fields replaced by the non-null parameter values. + @override + @JsonKey(includeFromJson: false, includeToJson: false) + _$$GitBranchImplCopyWith<_$GitBranchImpl> get copyWith => + throw _privateConstructorUsedError; +} + +DiffFile _$DiffFileFromJson(Map json) { + return _DiffFile.fromJson(json); +} + +/// @nodoc +mixin _$DiffFile { + String get path => throw _privateConstructorUsedError; + String get oldPath => throw _privateConstructorUsedError; + String get newPath => throw _privateConstructorUsedError; + FileChangeStatus get status => throw _privateConstructorUsedError; + int get additions => throw _privateConstructorUsedError; + int get deletions => throw _privateConstructorUsedError; + List get hunks => throw _privateConstructorUsedError; + String? get oldMode => throw _privateConstructorUsedError; + String? get newMode => throw _privateConstructorUsedError; + + /// Serializes this DiffFile to a JSON map. + Map toJson() => throw _privateConstructorUsedError; + + /// Create a copy of DiffFile + /// with the given fields replaced by the non-null parameter values. + @JsonKey(includeFromJson: false, includeToJson: false) + $DiffFileCopyWith get copyWith => + throw _privateConstructorUsedError; +} + +/// @nodoc +abstract class $DiffFileCopyWith<$Res> { + factory $DiffFileCopyWith(DiffFile value, $Res Function(DiffFile) then) = + _$DiffFileCopyWithImpl<$Res, DiffFile>; + @useResult + $Res call( + {String path, + String oldPath, + String newPath, + FileChangeStatus status, + int additions, + int deletions, + List hunks, + String? oldMode, + String? newMode}); +} + +/// @nodoc +class _$DiffFileCopyWithImpl<$Res, $Val extends DiffFile> + implements $DiffFileCopyWith<$Res> { + _$DiffFileCopyWithImpl(this._value, this._then); + + // ignore: unused_field + final $Val _value; + // ignore: unused_field + final $Res Function($Val) _then; + + /// Create a copy of DiffFile + /// with the given fields replaced by the non-null parameter values. + @pragma('vm:prefer-inline') + @override + $Res call({ + Object? path = null, + Object? oldPath = null, + Object? newPath = null, + Object? status = null, + Object? additions = null, + Object? deletions = null, + Object? hunks = null, + Object? oldMode = freezed, + Object? newMode = freezed, + }) { + return _then(_value.copyWith( + path: null == path + ? _value.path + : path // ignore: cast_nullable_to_non_nullable + as String, + oldPath: null == oldPath + ? _value.oldPath + : oldPath // ignore: cast_nullable_to_non_nullable + as String, + newPath: null == newPath + ? _value.newPath + : newPath // ignore: cast_nullable_to_non_nullable + as String, + status: null == status + ? _value.status + : status // ignore: cast_nullable_to_non_nullable + as FileChangeStatus, + additions: null == additions + ? _value.additions + : additions // ignore: cast_nullable_to_non_nullable + as int, + deletions: null == deletions + ? _value.deletions + : deletions // ignore: cast_nullable_to_non_nullable + as int, + hunks: null == hunks + ? _value.hunks + : hunks // ignore: cast_nullable_to_non_nullable + as List, + oldMode: freezed == oldMode + ? _value.oldMode + : oldMode // ignore: cast_nullable_to_non_nullable + as String?, + newMode: freezed == newMode + ? _value.newMode + : newMode // ignore: cast_nullable_to_non_nullable + as String?, + ) as $Val); + } +} + +/// @nodoc +abstract class _$$DiffFileImplCopyWith<$Res> + implements $DiffFileCopyWith<$Res> { + factory _$$DiffFileImplCopyWith( + _$DiffFileImpl value, $Res Function(_$DiffFileImpl) then) = + __$$DiffFileImplCopyWithImpl<$Res>; + @override + @useResult + $Res call( + {String path, + String oldPath, + String newPath, + FileChangeStatus status, + int additions, + int deletions, + List hunks, + String? oldMode, + String? newMode}); +} + +/// @nodoc +class __$$DiffFileImplCopyWithImpl<$Res> + extends _$DiffFileCopyWithImpl<$Res, _$DiffFileImpl> + implements _$$DiffFileImplCopyWith<$Res> { + __$$DiffFileImplCopyWithImpl( + _$DiffFileImpl _value, $Res Function(_$DiffFileImpl) _then) + : super(_value, _then); + + /// Create a copy of DiffFile + /// with the given fields replaced by the non-null parameter values. + @pragma('vm:prefer-inline') + @override + $Res call({ + Object? path = null, + Object? oldPath = null, + Object? newPath = null, + Object? status = null, + Object? additions = null, + Object? deletions = null, + Object? hunks = null, + Object? oldMode = freezed, + Object? newMode = freezed, + }) { + return _then(_$DiffFileImpl( + path: null == path + ? _value.path + : path // ignore: cast_nullable_to_non_nullable + as String, + oldPath: null == oldPath + ? _value.oldPath + : oldPath // ignore: cast_nullable_to_non_nullable + as String, + newPath: null == newPath + ? _value.newPath + : newPath // ignore: cast_nullable_to_non_nullable + as String, + status: null == status + ? _value.status + : status // ignore: cast_nullable_to_non_nullable + as FileChangeStatus, + additions: null == additions + ? _value.additions + : additions // ignore: cast_nullable_to_non_nullable + as int, + deletions: null == deletions + ? _value.deletions + : deletions // ignore: cast_nullable_to_non_nullable + as int, + hunks: null == hunks + ? _value._hunks + : hunks // ignore: cast_nullable_to_non_nullable + as List, + oldMode: freezed == oldMode + ? _value.oldMode + : oldMode // ignore: cast_nullable_to_non_nullable + as String?, + newMode: freezed == newMode + ? _value.newMode + : newMode // ignore: cast_nullable_to_non_nullable + as String?, + )); + } +} + +/// @nodoc +@JsonSerializable() +class _$DiffFileImpl implements _DiffFile { + const _$DiffFileImpl( + {required this.path, + required this.oldPath, + required this.newPath, + required this.status, + required this.additions, + required this.deletions, + required final List hunks, + this.oldMode, + this.newMode}) + : _hunks = hunks; + + factory _$DiffFileImpl.fromJson(Map json) => + _$$DiffFileImplFromJson(json); + + @override + final String path; + @override + final String oldPath; + @override + final String newPath; + @override + final FileChangeStatus status; + @override + final int additions; + @override + final int deletions; + final List _hunks; + @override + List get hunks { + if (_hunks is EqualUnmodifiableListView) return _hunks; + // ignore: implicit_dynamic_type + return EqualUnmodifiableListView(_hunks); + } + + @override + final String? oldMode; + @override + final String? newMode; + + @override + String toString() { + return 'DiffFile(path: $path, oldPath: $oldPath, newPath: $newPath, status: $status, additions: $additions, deletions: $deletions, hunks: $hunks, oldMode: $oldMode, newMode: $newMode)'; + } + + @override + bool operator ==(Object other) { + return identical(this, other) || + (other.runtimeType == runtimeType && + other is _$DiffFileImpl && + (identical(other.path, path) || other.path == path) && + (identical(other.oldPath, oldPath) || other.oldPath == oldPath) && + (identical(other.newPath, newPath) || other.newPath == newPath) && + (identical(other.status, status) || other.status == status) && + (identical(other.additions, additions) || + other.additions == additions) && + (identical(other.deletions, deletions) || + other.deletions == deletions) && + const DeepCollectionEquality().equals(other._hunks, _hunks) && + (identical(other.oldMode, oldMode) || other.oldMode == oldMode) && + (identical(other.newMode, newMode) || other.newMode == newMode)); + } + + @JsonKey(includeFromJson: false, includeToJson: false) + @override + int get hashCode => Object.hash( + runtimeType, + path, + oldPath, + newPath, + status, + additions, + deletions, + const DeepCollectionEquality().hash(_hunks), + oldMode, + newMode); + + /// Create a copy of DiffFile + /// with the given fields replaced by the non-null parameter values. + @JsonKey(includeFromJson: false, includeToJson: false) + @override + @pragma('vm:prefer-inline') + _$$DiffFileImplCopyWith<_$DiffFileImpl> get copyWith => + __$$DiffFileImplCopyWithImpl<_$DiffFileImpl>(this, _$identity); + + @override + Map toJson() { + return _$$DiffFileImplToJson( + this, + ); + } +} + +abstract class _DiffFile implements DiffFile { + const factory _DiffFile( + {required final String path, + required final String oldPath, + required final String newPath, + required final FileChangeStatus status, + required final int additions, + required final int deletions, + required final List hunks, + final String? oldMode, + final String? newMode}) = _$DiffFileImpl; + + factory _DiffFile.fromJson(Map json) = + _$DiffFileImpl.fromJson; + + @override + String get path; + @override + String get oldPath; + @override + String get newPath; + @override + FileChangeStatus get status; + @override + int get additions; + @override + int get deletions; + @override + List get hunks; + @override + String? get oldMode; + @override + String? get newMode; + + /// Create a copy of DiffFile + /// with the given fields replaced by the non-null parameter values. + @override + @JsonKey(includeFromJson: false, includeToJson: false) + _$$DiffFileImplCopyWith<_$DiffFileImpl> get copyWith => + throw _privateConstructorUsedError; +} + +DiffHunk _$DiffHunkFromJson(Map json) { + return _DiffHunk.fromJson(json); +} + +/// @nodoc +mixin _$DiffHunk { + String get header => throw _privateConstructorUsedError; + int get oldStart => throw _privateConstructorUsedError; + int get oldLines => throw _privateConstructorUsedError; + int get newStart => throw _privateConstructorUsedError; + int get newLines => throw _privateConstructorUsedError; + List get lines => throw _privateConstructorUsedError; + + /// Serializes this DiffHunk to a JSON map. + Map toJson() => throw _privateConstructorUsedError; + + /// Create a copy of DiffHunk + /// with the given fields replaced by the non-null parameter values. + @JsonKey(includeFromJson: false, includeToJson: false) + $DiffHunkCopyWith get copyWith => + throw _privateConstructorUsedError; +} + +/// @nodoc +abstract class $DiffHunkCopyWith<$Res> { + factory $DiffHunkCopyWith(DiffHunk value, $Res Function(DiffHunk) then) = + _$DiffHunkCopyWithImpl<$Res, DiffHunk>; + @useResult + $Res call( + {String header, + int oldStart, + int oldLines, + int newStart, + int newLines, + List lines}); +} + +/// @nodoc +class _$DiffHunkCopyWithImpl<$Res, $Val extends DiffHunk> + implements $DiffHunkCopyWith<$Res> { + _$DiffHunkCopyWithImpl(this._value, this._then); + + // ignore: unused_field + final $Val _value; + // ignore: unused_field + final $Res Function($Val) _then; + + /// Create a copy of DiffHunk + /// with the given fields replaced by the non-null parameter values. + @pragma('vm:prefer-inline') + @override + $Res call({ + Object? header = null, + Object? oldStart = null, + Object? oldLines = null, + Object? newStart = null, + Object? newLines = null, + Object? lines = null, + }) { + return _then(_value.copyWith( + header: null == header + ? _value.header + : header // ignore: cast_nullable_to_non_nullable + as String, + oldStart: null == oldStart + ? _value.oldStart + : oldStart // ignore: cast_nullable_to_non_nullable + as int, + oldLines: null == oldLines + ? _value.oldLines + : oldLines // ignore: cast_nullable_to_non_nullable + as int, + newStart: null == newStart + ? _value.newStart + : newStart // ignore: cast_nullable_to_non_nullable + as int, + newLines: null == newLines + ? _value.newLines + : newLines // ignore: cast_nullable_to_non_nullable + as int, + lines: null == lines + ? _value.lines + : lines // ignore: cast_nullable_to_non_nullable + as List, + ) as $Val); + } +} + +/// @nodoc +abstract class _$$DiffHunkImplCopyWith<$Res> + implements $DiffHunkCopyWith<$Res> { + factory _$$DiffHunkImplCopyWith( + _$DiffHunkImpl value, $Res Function(_$DiffHunkImpl) then) = + __$$DiffHunkImplCopyWithImpl<$Res>; + @override + @useResult + $Res call( + {String header, + int oldStart, + int oldLines, + int newStart, + int newLines, + List lines}); +} + +/// @nodoc +class __$$DiffHunkImplCopyWithImpl<$Res> + extends _$DiffHunkCopyWithImpl<$Res, _$DiffHunkImpl> + implements _$$DiffHunkImplCopyWith<$Res> { + __$$DiffHunkImplCopyWithImpl( + _$DiffHunkImpl _value, $Res Function(_$DiffHunkImpl) _then) + : super(_value, _then); + + /// Create a copy of DiffHunk + /// with the given fields replaced by the non-null parameter values. + @pragma('vm:prefer-inline') + @override + $Res call({ + Object? header = null, + Object? oldStart = null, + Object? oldLines = null, + Object? newStart = null, + Object? newLines = null, + Object? lines = null, + }) { + return _then(_$DiffHunkImpl( + header: null == header + ? _value.header + : header // ignore: cast_nullable_to_non_nullable + as String, + oldStart: null == oldStart + ? _value.oldStart + : oldStart // ignore: cast_nullable_to_non_nullable + as int, + oldLines: null == oldLines + ? _value.oldLines + : oldLines // ignore: cast_nullable_to_non_nullable + as int, + newStart: null == newStart + ? _value.newStart + : newStart // ignore: cast_nullable_to_non_nullable + as int, + newLines: null == newLines + ? _value.newLines + : newLines // ignore: cast_nullable_to_non_nullable + as int, + lines: null == lines + ? _value._lines + : lines // ignore: cast_nullable_to_non_nullable + as List, + )); + } +} + +/// @nodoc +@JsonSerializable() +class _$DiffHunkImpl implements _DiffHunk { + const _$DiffHunkImpl( + {required this.header, + required this.oldStart, + required this.oldLines, + required this.newStart, + required this.newLines, + required final List lines}) + : _lines = lines; + + factory _$DiffHunkImpl.fromJson(Map json) => + _$$DiffHunkImplFromJson(json); + + @override + final String header; + @override + final int oldStart; + @override + final int oldLines; + @override + final int newStart; + @override + final int newLines; + final List _lines; + @override + List get lines { + if (_lines is EqualUnmodifiableListView) return _lines; + // ignore: implicit_dynamic_type + return EqualUnmodifiableListView(_lines); + } + + @override + String toString() { + return 'DiffHunk(header: $header, oldStart: $oldStart, oldLines: $oldLines, newStart: $newStart, newLines: $newLines, lines: $lines)'; + } + + @override + bool operator ==(Object other) { + return identical(this, other) || + (other.runtimeType == runtimeType && + other is _$DiffHunkImpl && + (identical(other.header, header) || other.header == header) && + (identical(other.oldStart, oldStart) || + other.oldStart == oldStart) && + (identical(other.oldLines, oldLines) || + other.oldLines == oldLines) && + (identical(other.newStart, newStart) || + other.newStart == newStart) && + (identical(other.newLines, newLines) || + other.newLines == newLines) && + const DeepCollectionEquality().equals(other._lines, _lines)); + } + + @JsonKey(includeFromJson: false, includeToJson: false) + @override + int get hashCode => Object.hash(runtimeType, header, oldStart, oldLines, + newStart, newLines, const DeepCollectionEquality().hash(_lines)); + + /// Create a copy of DiffHunk + /// with the given fields replaced by the non-null parameter values. + @JsonKey(includeFromJson: false, includeToJson: false) + @override + @pragma('vm:prefer-inline') + _$$DiffHunkImplCopyWith<_$DiffHunkImpl> get copyWith => + __$$DiffHunkImplCopyWithImpl<_$DiffHunkImpl>(this, _$identity); + + @override + Map toJson() { + return _$$DiffHunkImplToJson( + this, + ); + } +} + +abstract class _DiffHunk implements DiffHunk { + const factory _DiffHunk( + {required final String header, + required final int oldStart, + required final int oldLines, + required final int newStart, + required final int newLines, + required final List lines}) = _$DiffHunkImpl; + + factory _DiffHunk.fromJson(Map json) = + _$DiffHunkImpl.fromJson; + + @override + String get header; + @override + int get oldStart; + @override + int get oldLines; + @override + int get newStart; + @override + int get newLines; + @override + List get lines; + + /// Create a copy of DiffHunk + /// with the given fields replaced by the non-null parameter values. + @override + @JsonKey(includeFromJson: false, includeToJson: false) + _$$DiffHunkImplCopyWith<_$DiffHunkImpl> get copyWith => + throw _privateConstructorUsedError; +} + +DiffLine _$DiffLineFromJson(Map json) { + return _DiffLine.fromJson(json); +} + +/// @nodoc +mixin _$DiffLine { + DiffLineType get type => throw _privateConstructorUsedError; + String get content => throw _privateConstructorUsedError; + int? get oldLineNumber => throw _privateConstructorUsedError; + int? get newLineNumber => throw _privateConstructorUsedError; + + /// Serializes this DiffLine to a JSON map. + Map toJson() => throw _privateConstructorUsedError; + + /// Create a copy of DiffLine + /// with the given fields replaced by the non-null parameter values. + @JsonKey(includeFromJson: false, includeToJson: false) + $DiffLineCopyWith get copyWith => + throw _privateConstructorUsedError; +} + +/// @nodoc +abstract class $DiffLineCopyWith<$Res> { + factory $DiffLineCopyWith(DiffLine value, $Res Function(DiffLine) then) = + _$DiffLineCopyWithImpl<$Res, DiffLine>; + @useResult + $Res call( + {DiffLineType type, + String content, + int? oldLineNumber, + int? newLineNumber}); +} + +/// @nodoc +class _$DiffLineCopyWithImpl<$Res, $Val extends DiffLine> + implements $DiffLineCopyWith<$Res> { + _$DiffLineCopyWithImpl(this._value, this._then); + + // ignore: unused_field + final $Val _value; + // ignore: unused_field + final $Res Function($Val) _then; + + /// Create a copy of DiffLine + /// with the given fields replaced by the non-null parameter values. + @pragma('vm:prefer-inline') + @override + $Res call({ + Object? type = null, + Object? content = null, + Object? oldLineNumber = freezed, + Object? newLineNumber = freezed, + }) { + return _then(_value.copyWith( + type: null == type + ? _value.type + : type // ignore: cast_nullable_to_non_nullable + as DiffLineType, + content: null == content + ? _value.content + : content // ignore: cast_nullable_to_non_nullable + as String, + oldLineNumber: freezed == oldLineNumber + ? _value.oldLineNumber + : oldLineNumber // ignore: cast_nullable_to_non_nullable + as int?, + newLineNumber: freezed == newLineNumber + ? _value.newLineNumber + : newLineNumber // ignore: cast_nullable_to_non_nullable + as int?, + ) as $Val); + } +} + +/// @nodoc +abstract class _$$DiffLineImplCopyWith<$Res> + implements $DiffLineCopyWith<$Res> { + factory _$$DiffLineImplCopyWith( + _$DiffLineImpl value, $Res Function(_$DiffLineImpl) then) = + __$$DiffLineImplCopyWithImpl<$Res>; + @override + @useResult + $Res call( + {DiffLineType type, + String content, + int? oldLineNumber, + int? newLineNumber}); +} + +/// @nodoc +class __$$DiffLineImplCopyWithImpl<$Res> + extends _$DiffLineCopyWithImpl<$Res, _$DiffLineImpl> + implements _$$DiffLineImplCopyWith<$Res> { + __$$DiffLineImplCopyWithImpl( + _$DiffLineImpl _value, $Res Function(_$DiffLineImpl) _then) + : super(_value, _then); + + /// Create a copy of DiffLine + /// with the given fields replaced by the non-null parameter values. + @pragma('vm:prefer-inline') + @override + $Res call({ + Object? type = null, + Object? content = null, + Object? oldLineNumber = freezed, + Object? newLineNumber = freezed, + }) { + return _then(_$DiffLineImpl( + type: null == type + ? _value.type + : type // ignore: cast_nullable_to_non_nullable + as DiffLineType, + content: null == content + ? _value.content + : content // ignore: cast_nullable_to_non_nullable + as String, + oldLineNumber: freezed == oldLineNumber + ? _value.oldLineNumber + : oldLineNumber // ignore: cast_nullable_to_non_nullable + as int?, + newLineNumber: freezed == newLineNumber + ? _value.newLineNumber + : newLineNumber // ignore: cast_nullable_to_non_nullable + as int?, + )); + } +} + +/// @nodoc +@JsonSerializable() +class _$DiffLineImpl implements _DiffLine { + const _$DiffLineImpl( + {required this.type, + required this.content, + this.oldLineNumber, + this.newLineNumber}); + + factory _$DiffLineImpl.fromJson(Map json) => + _$$DiffLineImplFromJson(json); + + @override + final DiffLineType type; + @override + final String content; + @override + final int? oldLineNumber; + @override + final int? newLineNumber; + + @override + String toString() { + return 'DiffLine(type: $type, content: $content, oldLineNumber: $oldLineNumber, newLineNumber: $newLineNumber)'; + } + + @override + bool operator ==(Object other) { + return identical(this, other) || + (other.runtimeType == runtimeType && + other is _$DiffLineImpl && + (identical(other.type, type) || other.type == type) && + (identical(other.content, content) || other.content == content) && + (identical(other.oldLineNumber, oldLineNumber) || + other.oldLineNumber == oldLineNumber) && + (identical(other.newLineNumber, newLineNumber) || + other.newLineNumber == newLineNumber)); + } + + @JsonKey(includeFromJson: false, includeToJson: false) + @override + int get hashCode => + Object.hash(runtimeType, type, content, oldLineNumber, newLineNumber); + + /// Create a copy of DiffLine + /// with the given fields replaced by the non-null parameter values. + @JsonKey(includeFromJson: false, includeToJson: false) + @override + @pragma('vm:prefer-inline') + _$$DiffLineImplCopyWith<_$DiffLineImpl> get copyWith => + __$$DiffLineImplCopyWithImpl<_$DiffLineImpl>(this, _$identity); + + @override + Map toJson() { + return _$$DiffLineImplToJson( + this, + ); + } +} + +abstract class _DiffLine implements DiffLine { + const factory _DiffLine( + {required final DiffLineType type, + required final String content, + final int? oldLineNumber, + final int? newLineNumber}) = _$DiffLineImpl; + + factory _DiffLine.fromJson(Map json) = + _$DiffLineImpl.fromJson; + + @override + DiffLineType get type; + @override + String get content; + @override + int? get oldLineNumber; + @override + int? get newLineNumber; + + /// Create a copy of DiffLine + /// with the given fields replaced by the non-null parameter values. + @override + @JsonKey(includeFromJson: false, includeToJson: false) + _$$DiffLineImplCopyWith<_$DiffLineImpl> get copyWith => + throw _privateConstructorUsedError; +} diff --git a/apps/mobile/lib/core/models/git_models.g.dart b/apps/mobile/lib/core/models/git_models.g.dart new file mode 100644 index 0000000..5c38070 --- /dev/null +++ b/apps/mobile/lib/core/models/git_models.g.dart @@ -0,0 +1,143 @@ +// GENERATED CODE - DO NOT MODIFY BY HAND + +part of 'git_models.dart'; + +// ************************************************************************** +// JsonSerializableGenerator +// ************************************************************************** + +_$GitStatusImpl _$$GitStatusImplFromJson(Map json) => + _$GitStatusImpl( + branch: json['branch'] as String, + changes: (json['changes'] as List) + .map((e) => GitFileChange.fromJson(e as Map)) + .toList(), + ahead: (json['ahead'] as num).toInt(), + behind: (json['behind'] as num).toInt(), + isClean: json['isClean'] as bool, + ); + +Map _$$GitStatusImplToJson(_$GitStatusImpl instance) => + { + 'branch': instance.branch, + 'changes': instance.changes, + 'ahead': instance.ahead, + 'behind': instance.behind, + 'isClean': instance.isClean, + }; + +_$GitFileChangeImpl _$$GitFileChangeImplFromJson(Map json) => + _$GitFileChangeImpl( + path: json['path'] as String, + status: $enumDecode(_$FileChangeStatusEnumMap, json['status']), + additions: (json['additions'] as num?)?.toInt(), + deletions: (json['deletions'] as num?)?.toInt(), + diff: json['diff'] as String?, + ); + +Map _$$GitFileChangeImplToJson(_$GitFileChangeImpl instance) => + { + 'path': instance.path, + 'status': _$FileChangeStatusEnumMap[instance.status]!, + 'additions': instance.additions, + 'deletions': instance.deletions, + 'diff': instance.diff, + }; + +const _$FileChangeStatusEnumMap = { + FileChangeStatus.modified: 'modified', + FileChangeStatus.added: 'added', + FileChangeStatus.deleted: 'deleted', + FileChangeStatus.untracked: 'untracked', + FileChangeStatus.renamed: 'renamed', +}; + +_$GitBranchImpl _$$GitBranchImplFromJson(Map json) => + _$GitBranchImpl( + name: json['name'] as String, + isCurrent: json['isCurrent'] as bool, + upstream: json['upstream'] as String?, + ahead: (json['ahead'] as num?)?.toInt(), + behind: (json['behind'] as num?)?.toInt(), + ); + +Map _$$GitBranchImplToJson(_$GitBranchImpl instance) => + { + 'name': instance.name, + 'isCurrent': instance.isCurrent, + 'upstream': instance.upstream, + 'ahead': instance.ahead, + 'behind': instance.behind, + }; + +_$DiffFileImpl _$$DiffFileImplFromJson(Map json) => + _$DiffFileImpl( + path: json['path'] as String, + oldPath: json['oldPath'] as String, + newPath: json['newPath'] as String, + status: $enumDecode(_$FileChangeStatusEnumMap, json['status']), + additions: (json['additions'] as num).toInt(), + deletions: (json['deletions'] as num).toInt(), + hunks: (json['hunks'] as List) + .map((e) => DiffHunk.fromJson(e as Map)) + .toList(), + oldMode: json['oldMode'] as String?, + newMode: json['newMode'] as String?, + ); + +Map _$$DiffFileImplToJson(_$DiffFileImpl instance) => + { + 'path': instance.path, + 'oldPath': instance.oldPath, + 'newPath': instance.newPath, + 'status': _$FileChangeStatusEnumMap[instance.status]!, + 'additions': instance.additions, + 'deletions': instance.deletions, + 'hunks': instance.hunks, + 'oldMode': instance.oldMode, + 'newMode': instance.newMode, + }; + +_$DiffHunkImpl _$$DiffHunkImplFromJson(Map json) => + _$DiffHunkImpl( + header: json['header'] as String, + oldStart: (json['oldStart'] as num).toInt(), + oldLines: (json['oldLines'] as num).toInt(), + newStart: (json['newStart'] as num).toInt(), + newLines: (json['newLines'] as num).toInt(), + lines: (json['lines'] as List) + .map((e) => DiffLine.fromJson(e as Map)) + .toList(), + ); + +Map _$$DiffHunkImplToJson(_$DiffHunkImpl instance) => + { + 'header': instance.header, + 'oldStart': instance.oldStart, + 'oldLines': instance.oldLines, + 'newStart': instance.newStart, + 'newLines': instance.newLines, + 'lines': instance.lines, + }; + +_$DiffLineImpl _$$DiffLineImplFromJson(Map json) => + _$DiffLineImpl( + type: $enumDecode(_$DiffLineTypeEnumMap, json['type']), + content: json['content'] as String, + oldLineNumber: (json['oldLineNumber'] as num?)?.toInt(), + newLineNumber: (json['newLineNumber'] as num?)?.toInt(), + ); + +Map _$$DiffLineImplToJson(_$DiffLineImpl instance) => + { + 'type': _$DiffLineTypeEnumMap[instance.type]!, + 'content': instance.content, + 'oldLineNumber': instance.oldLineNumber, + 'newLineNumber': instance.newLineNumber, + }; + +const _$DiffLineTypeEnumMap = { + DiffLineType.context: 'context', + DiffLineType.added: 'added', + DiffLineType.removed: 'removed', +}; diff --git a/apps/mobile/lib/core/models/hook_models.dart b/apps/mobile/lib/core/models/hook_models.dart new file mode 100644 index 0000000..ca80534 --- /dev/null +++ b/apps/mobile/lib/core/models/hook_models.dart @@ -0,0 +1,29 @@ +import 'package:freezed_annotation/freezed_annotation.dart'; + +part 'hook_models.freezed.dart'; +part 'hook_models.g.dart'; + +enum HookEventType { + sessionStart, + sessionEnd, + preToolUse, + postToolUse, + userPromptSubmit, + stop, + subagentStop, + preCompact, + notification, +} + +@freezed +class HookEvent with _$HookEvent { + const factory HookEvent({ + required String eventType, + required String sessionId, + required DateTime timestamp, + required Map payload, + }) = _HookEvent; + + factory HookEvent.fromJson(Map json) => + _$HookEventFromJson(json); +} diff --git a/apps/mobile/lib/core/models/hook_models.freezed.dart b/apps/mobile/lib/core/models/hook_models.freezed.dart new file mode 100644 index 0000000..73935f2 --- /dev/null +++ b/apps/mobile/lib/core/models/hook_models.freezed.dart @@ -0,0 +1,237 @@ +// coverage:ignore-file +// GENERATED CODE - DO NOT MODIFY BY HAND +// ignore_for_file: type=lint +// ignore_for_file: unused_element, deprecated_member_use, deprecated_member_use_from_same_package, use_function_type_syntax_for_parameters, unnecessary_const, avoid_init_to_null, invalid_override_different_default_values_named, prefer_expression_function_bodies, annotate_overrides, invalid_annotation_target, unnecessary_question_mark + +part of 'hook_models.dart'; + +// ************************************************************************** +// FreezedGenerator +// ************************************************************************** + +T _$identity(T value) => value; + +final _privateConstructorUsedError = UnsupportedError( + 'It seems like you constructed your class using `MyClass._()`. This constructor is only meant to be used by freezed and you are not supposed to need it nor use it.\nPlease check the documentation here for more information: https://github.com/rrousselGit/freezed#adding-getters-and-methods-to-our-models'); + +HookEvent _$HookEventFromJson(Map json) { + return _HookEvent.fromJson(json); +} + +/// @nodoc +mixin _$HookEvent { + String get eventType => throw _privateConstructorUsedError; + String get sessionId => throw _privateConstructorUsedError; + DateTime get timestamp => throw _privateConstructorUsedError; + Map get payload => throw _privateConstructorUsedError; + + /// Serializes this HookEvent to a JSON map. + Map toJson() => throw _privateConstructorUsedError; + + /// Create a copy of HookEvent + /// with the given fields replaced by the non-null parameter values. + @JsonKey(includeFromJson: false, includeToJson: false) + $HookEventCopyWith get copyWith => + throw _privateConstructorUsedError; +} + +/// @nodoc +abstract class $HookEventCopyWith<$Res> { + factory $HookEventCopyWith(HookEvent value, $Res Function(HookEvent) then) = + _$HookEventCopyWithImpl<$Res, HookEvent>; + @useResult + $Res call( + {String eventType, + String sessionId, + DateTime timestamp, + Map payload}); +} + +/// @nodoc +class _$HookEventCopyWithImpl<$Res, $Val extends HookEvent> + implements $HookEventCopyWith<$Res> { + _$HookEventCopyWithImpl(this._value, this._then); + + // ignore: unused_field + final $Val _value; + // ignore: unused_field + final $Res Function($Val) _then; + + /// Create a copy of HookEvent + /// with the given fields replaced by the non-null parameter values. + @pragma('vm:prefer-inline') + @override + $Res call({ + Object? eventType = null, + Object? sessionId = null, + Object? timestamp = null, + Object? payload = null, + }) { + return _then(_value.copyWith( + eventType: null == eventType + ? _value.eventType + : eventType // ignore: cast_nullable_to_non_nullable + as String, + sessionId: null == sessionId + ? _value.sessionId + : sessionId // ignore: cast_nullable_to_non_nullable + as String, + timestamp: null == timestamp + ? _value.timestamp + : timestamp // ignore: cast_nullable_to_non_nullable + as DateTime, + payload: null == payload + ? _value.payload + : payload // ignore: cast_nullable_to_non_nullable + as Map, + ) as $Val); + } +} + +/// @nodoc +abstract class _$$HookEventImplCopyWith<$Res> + implements $HookEventCopyWith<$Res> { + factory _$$HookEventImplCopyWith( + _$HookEventImpl value, $Res Function(_$HookEventImpl) then) = + __$$HookEventImplCopyWithImpl<$Res>; + @override + @useResult + $Res call( + {String eventType, + String sessionId, + DateTime timestamp, + Map payload}); +} + +/// @nodoc +class __$$HookEventImplCopyWithImpl<$Res> + extends _$HookEventCopyWithImpl<$Res, _$HookEventImpl> + implements _$$HookEventImplCopyWith<$Res> { + __$$HookEventImplCopyWithImpl( + _$HookEventImpl _value, $Res Function(_$HookEventImpl) _then) + : super(_value, _then); + + /// Create a copy of HookEvent + /// with the given fields replaced by the non-null parameter values. + @pragma('vm:prefer-inline') + @override + $Res call({ + Object? eventType = null, + Object? sessionId = null, + Object? timestamp = null, + Object? payload = null, + }) { + return _then(_$HookEventImpl( + eventType: null == eventType + ? _value.eventType + : eventType // ignore: cast_nullable_to_non_nullable + as String, + sessionId: null == sessionId + ? _value.sessionId + : sessionId // ignore: cast_nullable_to_non_nullable + as String, + timestamp: null == timestamp + ? _value.timestamp + : timestamp // ignore: cast_nullable_to_non_nullable + as DateTime, + payload: null == payload + ? _value._payload + : payload // ignore: cast_nullable_to_non_nullable + as Map, + )); + } +} + +/// @nodoc +@JsonSerializable() +class _$HookEventImpl implements _HookEvent { + const _$HookEventImpl( + {required this.eventType, + required this.sessionId, + required this.timestamp, + required final Map payload}) + : _payload = payload; + + factory _$HookEventImpl.fromJson(Map json) => + _$$HookEventImplFromJson(json); + + @override + final String eventType; + @override + final String sessionId; + @override + final DateTime timestamp; + final Map _payload; + @override + Map get payload { + if (_payload is EqualUnmodifiableMapView) return _payload; + // ignore: implicit_dynamic_type + return EqualUnmodifiableMapView(_payload); + } + + @override + String toString() { + return 'HookEvent(eventType: $eventType, sessionId: $sessionId, timestamp: $timestamp, payload: $payload)'; + } + + @override + bool operator ==(Object other) { + return identical(this, other) || + (other.runtimeType == runtimeType && + other is _$HookEventImpl && + (identical(other.eventType, eventType) || + other.eventType == eventType) && + (identical(other.sessionId, sessionId) || + other.sessionId == sessionId) && + (identical(other.timestamp, timestamp) || + other.timestamp == timestamp) && + const DeepCollectionEquality().equals(other._payload, _payload)); + } + + @JsonKey(includeFromJson: false, includeToJson: false) + @override + int get hashCode => Object.hash(runtimeType, eventType, sessionId, timestamp, + const DeepCollectionEquality().hash(_payload)); + + /// Create a copy of HookEvent + /// with the given fields replaced by the non-null parameter values. + @JsonKey(includeFromJson: false, includeToJson: false) + @override + @pragma('vm:prefer-inline') + _$$HookEventImplCopyWith<_$HookEventImpl> get copyWith => + __$$HookEventImplCopyWithImpl<_$HookEventImpl>(this, _$identity); + + @override + Map toJson() { + return _$$HookEventImplToJson( + this, + ); + } +} + +abstract class _HookEvent implements HookEvent { + const factory _HookEvent( + {required final String eventType, + required final String sessionId, + required final DateTime timestamp, + required final Map payload}) = _$HookEventImpl; + + factory _HookEvent.fromJson(Map json) = + _$HookEventImpl.fromJson; + + @override + String get eventType; + @override + String get sessionId; + @override + DateTime get timestamp; + @override + Map get payload; + + /// Create a copy of HookEvent + /// with the given fields replaced by the non-null parameter values. + @override + @JsonKey(includeFromJson: false, includeToJson: false) + _$$HookEventImplCopyWith<_$HookEventImpl> get copyWith => + throw _privateConstructorUsedError; +} diff --git a/apps/mobile/lib/core/models/hook_models.g.dart b/apps/mobile/lib/core/models/hook_models.g.dart new file mode 100644 index 0000000..142077b --- /dev/null +++ b/apps/mobile/lib/core/models/hook_models.g.dart @@ -0,0 +1,23 @@ +// GENERATED CODE - DO NOT MODIFY BY HAND + +part of 'hook_models.dart'; + +// ************************************************************************** +// JsonSerializableGenerator +// ************************************************************************** + +_$HookEventImpl _$$HookEventImplFromJson(Map json) => + _$HookEventImpl( + eventType: json['eventType'] as String, + sessionId: json['sessionId'] as String, + timestamp: DateTime.parse(json['timestamp'] as String), + payload: json['payload'] as Map, + ); + +Map _$$HookEventImplToJson(_$HookEventImpl instance) => + { + 'eventType': instance.eventType, + 'sessionId': instance.sessionId, + 'timestamp': instance.timestamp.toIso8601String(), + 'payload': instance.payload, + }; diff --git a/apps/mobile/lib/core/models/message_models.dart b/apps/mobile/lib/core/models/message_models.dart new file mode 100644 index 0000000..45c9822 --- /dev/null +++ b/apps/mobile/lib/core/models/message_models.dart @@ -0,0 +1,91 @@ +import 'package:freezed_annotation/freezed_annotation.dart'; + +part 'message_models.freezed.dart'; +part 'message_models.g.dart'; + +enum MessageRole { user, agent, system } + +enum MessageType { text, toolCall, toolResult, system } + +@freezed +class MessagePart with _$MessagePart { + const factory MessagePart.text({ + required String content, + }) = TextPart; + + const factory MessagePart.toolUse({ + required String tool, + required Map params, + String? id, + }) = ToolUsePart; + + const factory MessagePart.toolResult({ + required String toolCallId, + required ToolResult result, + }) = ToolResultPart; + + const factory MessagePart.thinking({ + required String content, + }) = ThinkingPart; + + factory MessagePart.fromJson(Map json) => + _$MessagePartFromJson(json); +} + +@freezed +class ToolResult with _$ToolResult { + const factory ToolResult({ + required bool success, + required String content, + Map? metadata, + String? error, + int? durationMs, + }) = _ToolResult; + + factory ToolResult.fromJson(Map json) => + _$ToolResultFromJson(json); +} + +enum RiskLevel { low, medium, high, critical } + +enum ApprovalDecision { pending, approved, rejected, modified } + +@freezed +class ToolCall with _$ToolCall { + const factory ToolCall({ + required String id, + required String sessionId, + required String tool, + required Map params, + String? description, + String? reasoning, + @Default(RiskLevel.low) RiskLevel riskLevel, + @Default(ApprovalDecision.pending) ApprovalDecision decision, + String? modifications, + Map? result, + required DateTime createdAt, + DateTime? decidedAt, + }) = _ToolCall; + + factory ToolCall.fromJson(Map json) => + _$ToolCallFromJson(json); +} + +@freezed +class Message with _$Message { + const factory Message({ + required String id, + required String sessionId, + required MessageRole role, + required String content, + required MessageType type, + required List parts, + Map? metadata, + required DateTime createdAt, + DateTime? updatedAt, + @Default(true) bool synced, + }) = _Message; + + factory Message.fromJson(Map json) => + _$MessageFromJson(json); +} diff --git a/apps/mobile/lib/core/models/message_models.freezed.dart b/apps/mobile/lib/core/models/message_models.freezed.dart new file mode 100644 index 0000000..771541f --- /dev/null +++ b/apps/mobile/lib/core/models/message_models.freezed.dart @@ -0,0 +1,1885 @@ +// coverage:ignore-file +// GENERATED CODE - DO NOT MODIFY BY HAND +// ignore_for_file: type=lint +// ignore_for_file: unused_element, deprecated_member_use, deprecated_member_use_from_same_package, use_function_type_syntax_for_parameters, unnecessary_const, avoid_init_to_null, invalid_override_different_default_values_named, prefer_expression_function_bodies, annotate_overrides, invalid_annotation_target, unnecessary_question_mark + +part of 'message_models.dart'; + +// ************************************************************************** +// FreezedGenerator +// ************************************************************************** + +T _$identity(T value) => value; + +final _privateConstructorUsedError = UnsupportedError( + 'It seems like you constructed your class using `MyClass._()`. This constructor is only meant to be used by freezed and you are not supposed to need it nor use it.\nPlease check the documentation here for more information: https://github.com/rrousselGit/freezed#adding-getters-and-methods-to-our-models'); + +MessagePart _$MessagePartFromJson(Map json) { + switch (json['runtimeType']) { + case 'text': + return TextPart.fromJson(json); + case 'toolUse': + return ToolUsePart.fromJson(json); + case 'toolResult': + return ToolResultPart.fromJson(json); + case 'thinking': + return ThinkingPart.fromJson(json); + + default: + throw CheckedFromJsonException(json, 'runtimeType', 'MessagePart', + 'Invalid union type "${json['runtimeType']}"!'); + } +} + +/// @nodoc +mixin _$MessagePart { + @optionalTypeArgs + TResult when({ + required TResult Function(String content) text, + required TResult Function( + String tool, Map params, String? id) + toolUse, + required TResult Function(String toolCallId, ToolResult result) toolResult, + required TResult Function(String content) thinking, + }) => + throw _privateConstructorUsedError; + @optionalTypeArgs + TResult? whenOrNull({ + TResult? Function(String content)? text, + TResult? Function(String tool, Map params, String? id)? + toolUse, + TResult? Function(String toolCallId, ToolResult result)? toolResult, + TResult? Function(String content)? thinking, + }) => + throw _privateConstructorUsedError; + @optionalTypeArgs + TResult maybeWhen({ + TResult Function(String content)? text, + TResult Function(String tool, Map params, String? id)? + toolUse, + TResult Function(String toolCallId, ToolResult result)? toolResult, + TResult Function(String content)? thinking, + required TResult orElse(), + }) => + throw _privateConstructorUsedError; + @optionalTypeArgs + TResult map({ + required TResult Function(TextPart value) text, + required TResult Function(ToolUsePart value) toolUse, + required TResult Function(ToolResultPart value) toolResult, + required TResult Function(ThinkingPart value) thinking, + }) => + throw _privateConstructorUsedError; + @optionalTypeArgs + TResult? mapOrNull({ + TResult? Function(TextPart value)? text, + TResult? Function(ToolUsePart value)? toolUse, + TResult? Function(ToolResultPart value)? toolResult, + TResult? Function(ThinkingPart value)? thinking, + }) => + throw _privateConstructorUsedError; + @optionalTypeArgs + TResult maybeMap({ + TResult Function(TextPart value)? text, + TResult Function(ToolUsePart value)? toolUse, + TResult Function(ToolResultPart value)? toolResult, + TResult Function(ThinkingPart value)? thinking, + required TResult orElse(), + }) => + throw _privateConstructorUsedError; + + /// Serializes this MessagePart to a JSON map. + Map toJson() => throw _privateConstructorUsedError; +} + +/// @nodoc +abstract class $MessagePartCopyWith<$Res> { + factory $MessagePartCopyWith( + MessagePart value, $Res Function(MessagePart) then) = + _$MessagePartCopyWithImpl<$Res, MessagePart>; +} + +/// @nodoc +class _$MessagePartCopyWithImpl<$Res, $Val extends MessagePart> + implements $MessagePartCopyWith<$Res> { + _$MessagePartCopyWithImpl(this._value, this._then); + + // ignore: unused_field + final $Val _value; + // ignore: unused_field + final $Res Function($Val) _then; + + /// Create a copy of MessagePart + /// with the given fields replaced by the non-null parameter values. +} + +/// @nodoc +abstract class _$$TextPartImplCopyWith<$Res> { + factory _$$TextPartImplCopyWith( + _$TextPartImpl value, $Res Function(_$TextPartImpl) then) = + __$$TextPartImplCopyWithImpl<$Res>; + @useResult + $Res call({String content}); +} + +/// @nodoc +class __$$TextPartImplCopyWithImpl<$Res> + extends _$MessagePartCopyWithImpl<$Res, _$TextPartImpl> + implements _$$TextPartImplCopyWith<$Res> { + __$$TextPartImplCopyWithImpl( + _$TextPartImpl _value, $Res Function(_$TextPartImpl) _then) + : super(_value, _then); + + /// Create a copy of MessagePart + /// with the given fields replaced by the non-null parameter values. + @pragma('vm:prefer-inline') + @override + $Res call({ + Object? content = null, + }) { + return _then(_$TextPartImpl( + content: null == content + ? _value.content + : content // ignore: cast_nullable_to_non_nullable + as String, + )); + } +} + +/// @nodoc +@JsonSerializable() +class _$TextPartImpl implements TextPart { + const _$TextPartImpl({required this.content, final String? $type}) + : $type = $type ?? 'text'; + + factory _$TextPartImpl.fromJson(Map json) => + _$$TextPartImplFromJson(json); + + @override + final String content; + + @JsonKey(name: 'runtimeType') + final String $type; + + @override + String toString() { + return 'MessagePart.text(content: $content)'; + } + + @override + bool operator ==(Object other) { + return identical(this, other) || + (other.runtimeType == runtimeType && + other is _$TextPartImpl && + (identical(other.content, content) || other.content == content)); + } + + @JsonKey(includeFromJson: false, includeToJson: false) + @override + int get hashCode => Object.hash(runtimeType, content); + + /// Create a copy of MessagePart + /// with the given fields replaced by the non-null parameter values. + @JsonKey(includeFromJson: false, includeToJson: false) + @override + @pragma('vm:prefer-inline') + _$$TextPartImplCopyWith<_$TextPartImpl> get copyWith => + __$$TextPartImplCopyWithImpl<_$TextPartImpl>(this, _$identity); + + @override + @optionalTypeArgs + TResult when({ + required TResult Function(String content) text, + required TResult Function( + String tool, Map params, String? id) + toolUse, + required TResult Function(String toolCallId, ToolResult result) toolResult, + required TResult Function(String content) thinking, + }) { + return text(content); + } + + @override + @optionalTypeArgs + TResult? whenOrNull({ + TResult? Function(String content)? text, + TResult? Function(String tool, Map params, String? id)? + toolUse, + TResult? Function(String toolCallId, ToolResult result)? toolResult, + TResult? Function(String content)? thinking, + }) { + return text?.call(content); + } + + @override + @optionalTypeArgs + TResult maybeWhen({ + TResult Function(String content)? text, + TResult Function(String tool, Map params, String? id)? + toolUse, + TResult Function(String toolCallId, ToolResult result)? toolResult, + TResult Function(String content)? thinking, + required TResult orElse(), + }) { + if (text != null) { + return text(content); + } + return orElse(); + } + + @override + @optionalTypeArgs + TResult map({ + required TResult Function(TextPart value) text, + required TResult Function(ToolUsePart value) toolUse, + required TResult Function(ToolResultPart value) toolResult, + required TResult Function(ThinkingPart value) thinking, + }) { + return text(this); + } + + @override + @optionalTypeArgs + TResult? mapOrNull({ + TResult? Function(TextPart value)? text, + TResult? Function(ToolUsePart value)? toolUse, + TResult? Function(ToolResultPart value)? toolResult, + TResult? Function(ThinkingPart value)? thinking, + }) { + return text?.call(this); + } + + @override + @optionalTypeArgs + TResult maybeMap({ + TResult Function(TextPart value)? text, + TResult Function(ToolUsePart value)? toolUse, + TResult Function(ToolResultPart value)? toolResult, + TResult Function(ThinkingPart value)? thinking, + required TResult orElse(), + }) { + if (text != null) { + return text(this); + } + return orElse(); + } + + @override + Map toJson() { + return _$$TextPartImplToJson( + this, + ); + } +} + +abstract class TextPart implements MessagePart { + const factory TextPart({required final String content}) = _$TextPartImpl; + + factory TextPart.fromJson(Map json) = + _$TextPartImpl.fromJson; + + String get content; + + /// Create a copy of MessagePart + /// with the given fields replaced by the non-null parameter values. + @JsonKey(includeFromJson: false, includeToJson: false) + _$$TextPartImplCopyWith<_$TextPartImpl> get copyWith => + throw _privateConstructorUsedError; +} + +/// @nodoc +abstract class _$$ToolUsePartImplCopyWith<$Res> { + factory _$$ToolUsePartImplCopyWith( + _$ToolUsePartImpl value, $Res Function(_$ToolUsePartImpl) then) = + __$$ToolUsePartImplCopyWithImpl<$Res>; + @useResult + $Res call({String tool, Map params, String? id}); +} + +/// @nodoc +class __$$ToolUsePartImplCopyWithImpl<$Res> + extends _$MessagePartCopyWithImpl<$Res, _$ToolUsePartImpl> + implements _$$ToolUsePartImplCopyWith<$Res> { + __$$ToolUsePartImplCopyWithImpl( + _$ToolUsePartImpl _value, $Res Function(_$ToolUsePartImpl) _then) + : super(_value, _then); + + /// Create a copy of MessagePart + /// with the given fields replaced by the non-null parameter values. + @pragma('vm:prefer-inline') + @override + $Res call({ + Object? tool = null, + Object? params = null, + Object? id = freezed, + }) { + return _then(_$ToolUsePartImpl( + tool: null == tool + ? _value.tool + : tool // ignore: cast_nullable_to_non_nullable + as String, + params: null == params + ? _value._params + : params // ignore: cast_nullable_to_non_nullable + as Map, + id: freezed == id + ? _value.id + : id // ignore: cast_nullable_to_non_nullable + as String?, + )); + } +} + +/// @nodoc +@JsonSerializable() +class _$ToolUsePartImpl implements ToolUsePart { + const _$ToolUsePartImpl( + {required this.tool, + required final Map params, + this.id, + final String? $type}) + : _params = params, + $type = $type ?? 'toolUse'; + + factory _$ToolUsePartImpl.fromJson(Map json) => + _$$ToolUsePartImplFromJson(json); + + @override + final String tool; + final Map _params; + @override + Map get params { + if (_params is EqualUnmodifiableMapView) return _params; + // ignore: implicit_dynamic_type + return EqualUnmodifiableMapView(_params); + } + + @override + final String? id; + + @JsonKey(name: 'runtimeType') + final String $type; + + @override + String toString() { + return 'MessagePart.toolUse(tool: $tool, params: $params, id: $id)'; + } + + @override + bool operator ==(Object other) { + return identical(this, other) || + (other.runtimeType == runtimeType && + other is _$ToolUsePartImpl && + (identical(other.tool, tool) || other.tool == tool) && + const DeepCollectionEquality().equals(other._params, _params) && + (identical(other.id, id) || other.id == id)); + } + + @JsonKey(includeFromJson: false, includeToJson: false) + @override + int get hashCode => Object.hash( + runtimeType, tool, const DeepCollectionEquality().hash(_params), id); + + /// Create a copy of MessagePart + /// with the given fields replaced by the non-null parameter values. + @JsonKey(includeFromJson: false, includeToJson: false) + @override + @pragma('vm:prefer-inline') + _$$ToolUsePartImplCopyWith<_$ToolUsePartImpl> get copyWith => + __$$ToolUsePartImplCopyWithImpl<_$ToolUsePartImpl>(this, _$identity); + + @override + @optionalTypeArgs + TResult when({ + required TResult Function(String content) text, + required TResult Function( + String tool, Map params, String? id) + toolUse, + required TResult Function(String toolCallId, ToolResult result) toolResult, + required TResult Function(String content) thinking, + }) { + return toolUse(tool, params, id); + } + + @override + @optionalTypeArgs + TResult? whenOrNull({ + TResult? Function(String content)? text, + TResult? Function(String tool, Map params, String? id)? + toolUse, + TResult? Function(String toolCallId, ToolResult result)? toolResult, + TResult? Function(String content)? thinking, + }) { + return toolUse?.call(tool, params, id); + } + + @override + @optionalTypeArgs + TResult maybeWhen({ + TResult Function(String content)? text, + TResult Function(String tool, Map params, String? id)? + toolUse, + TResult Function(String toolCallId, ToolResult result)? toolResult, + TResult Function(String content)? thinking, + required TResult orElse(), + }) { + if (toolUse != null) { + return toolUse(tool, params, id); + } + return orElse(); + } + + @override + @optionalTypeArgs + TResult map({ + required TResult Function(TextPart value) text, + required TResult Function(ToolUsePart value) toolUse, + required TResult Function(ToolResultPart value) toolResult, + required TResult Function(ThinkingPart value) thinking, + }) { + return toolUse(this); + } + + @override + @optionalTypeArgs + TResult? mapOrNull({ + TResult? Function(TextPart value)? text, + TResult? Function(ToolUsePart value)? toolUse, + TResult? Function(ToolResultPart value)? toolResult, + TResult? Function(ThinkingPart value)? thinking, + }) { + return toolUse?.call(this); + } + + @override + @optionalTypeArgs + TResult maybeMap({ + TResult Function(TextPart value)? text, + TResult Function(ToolUsePart value)? toolUse, + TResult Function(ToolResultPart value)? toolResult, + TResult Function(ThinkingPart value)? thinking, + required TResult orElse(), + }) { + if (toolUse != null) { + return toolUse(this); + } + return orElse(); + } + + @override + Map toJson() { + return _$$ToolUsePartImplToJson( + this, + ); + } +} + +abstract class ToolUsePart implements MessagePart { + const factory ToolUsePart( + {required final String tool, + required final Map params, + final String? id}) = _$ToolUsePartImpl; + + factory ToolUsePart.fromJson(Map json) = + _$ToolUsePartImpl.fromJson; + + String get tool; + Map get params; + String? get id; + + /// Create a copy of MessagePart + /// with the given fields replaced by the non-null parameter values. + @JsonKey(includeFromJson: false, includeToJson: false) + _$$ToolUsePartImplCopyWith<_$ToolUsePartImpl> get copyWith => + throw _privateConstructorUsedError; +} + +/// @nodoc +abstract class _$$ToolResultPartImplCopyWith<$Res> { + factory _$$ToolResultPartImplCopyWith(_$ToolResultPartImpl value, + $Res Function(_$ToolResultPartImpl) then) = + __$$ToolResultPartImplCopyWithImpl<$Res>; + @useResult + $Res call({String toolCallId, ToolResult result}); + + $ToolResultCopyWith<$Res> get result; +} + +/// @nodoc +class __$$ToolResultPartImplCopyWithImpl<$Res> + extends _$MessagePartCopyWithImpl<$Res, _$ToolResultPartImpl> + implements _$$ToolResultPartImplCopyWith<$Res> { + __$$ToolResultPartImplCopyWithImpl( + _$ToolResultPartImpl _value, $Res Function(_$ToolResultPartImpl) _then) + : super(_value, _then); + + /// Create a copy of MessagePart + /// with the given fields replaced by the non-null parameter values. + @pragma('vm:prefer-inline') + @override + $Res call({ + Object? toolCallId = null, + Object? result = null, + }) { + return _then(_$ToolResultPartImpl( + toolCallId: null == toolCallId + ? _value.toolCallId + : toolCallId // ignore: cast_nullable_to_non_nullable + as String, + result: null == result + ? _value.result + : result // ignore: cast_nullable_to_non_nullable + as ToolResult, + )); + } + + /// Create a copy of MessagePart + /// with the given fields replaced by the non-null parameter values. + @override + @pragma('vm:prefer-inline') + $ToolResultCopyWith<$Res> get result { + return $ToolResultCopyWith<$Res>(_value.result, (value) { + return _then(_value.copyWith(result: value)); + }); + } +} + +/// @nodoc +@JsonSerializable() +class _$ToolResultPartImpl implements ToolResultPart { + const _$ToolResultPartImpl( + {required this.toolCallId, required this.result, final String? $type}) + : $type = $type ?? 'toolResult'; + + factory _$ToolResultPartImpl.fromJson(Map json) => + _$$ToolResultPartImplFromJson(json); + + @override + final String toolCallId; + @override + final ToolResult result; + + @JsonKey(name: 'runtimeType') + final String $type; + + @override + String toString() { + return 'MessagePart.toolResult(toolCallId: $toolCallId, result: $result)'; + } + + @override + bool operator ==(Object other) { + return identical(this, other) || + (other.runtimeType == runtimeType && + other is _$ToolResultPartImpl && + (identical(other.toolCallId, toolCallId) || + other.toolCallId == toolCallId) && + (identical(other.result, result) || other.result == result)); + } + + @JsonKey(includeFromJson: false, includeToJson: false) + @override + int get hashCode => Object.hash(runtimeType, toolCallId, result); + + /// Create a copy of MessagePart + /// with the given fields replaced by the non-null parameter values. + @JsonKey(includeFromJson: false, includeToJson: false) + @override + @pragma('vm:prefer-inline') + _$$ToolResultPartImplCopyWith<_$ToolResultPartImpl> get copyWith => + __$$ToolResultPartImplCopyWithImpl<_$ToolResultPartImpl>( + this, _$identity); + + @override + @optionalTypeArgs + TResult when({ + required TResult Function(String content) text, + required TResult Function( + String tool, Map params, String? id) + toolUse, + required TResult Function(String toolCallId, ToolResult result) toolResult, + required TResult Function(String content) thinking, + }) { + return toolResult(toolCallId, result); + } + + @override + @optionalTypeArgs + TResult? whenOrNull({ + TResult? Function(String content)? text, + TResult? Function(String tool, Map params, String? id)? + toolUse, + TResult? Function(String toolCallId, ToolResult result)? toolResult, + TResult? Function(String content)? thinking, + }) { + return toolResult?.call(toolCallId, result); + } + + @override + @optionalTypeArgs + TResult maybeWhen({ + TResult Function(String content)? text, + TResult Function(String tool, Map params, String? id)? + toolUse, + TResult Function(String toolCallId, ToolResult result)? toolResult, + TResult Function(String content)? thinking, + required TResult orElse(), + }) { + if (toolResult != null) { + return toolResult(toolCallId, result); + } + return orElse(); + } + + @override + @optionalTypeArgs + TResult map({ + required TResult Function(TextPart value) text, + required TResult Function(ToolUsePart value) toolUse, + required TResult Function(ToolResultPart value) toolResult, + required TResult Function(ThinkingPart value) thinking, + }) { + return toolResult(this); + } + + @override + @optionalTypeArgs + TResult? mapOrNull({ + TResult? Function(TextPart value)? text, + TResult? Function(ToolUsePart value)? toolUse, + TResult? Function(ToolResultPart value)? toolResult, + TResult? Function(ThinkingPart value)? thinking, + }) { + return toolResult?.call(this); + } + + @override + @optionalTypeArgs + TResult maybeMap({ + TResult Function(TextPart value)? text, + TResult Function(ToolUsePart value)? toolUse, + TResult Function(ToolResultPart value)? toolResult, + TResult Function(ThinkingPart value)? thinking, + required TResult orElse(), + }) { + if (toolResult != null) { + return toolResult(this); + } + return orElse(); + } + + @override + Map toJson() { + return _$$ToolResultPartImplToJson( + this, + ); + } +} + +abstract class ToolResultPart implements MessagePart { + const factory ToolResultPart( + {required final String toolCallId, + required final ToolResult result}) = _$ToolResultPartImpl; + + factory ToolResultPart.fromJson(Map json) = + _$ToolResultPartImpl.fromJson; + + String get toolCallId; + ToolResult get result; + + /// Create a copy of MessagePart + /// with the given fields replaced by the non-null parameter values. + @JsonKey(includeFromJson: false, includeToJson: false) + _$$ToolResultPartImplCopyWith<_$ToolResultPartImpl> get copyWith => + throw _privateConstructorUsedError; +} + +/// @nodoc +abstract class _$$ThinkingPartImplCopyWith<$Res> { + factory _$$ThinkingPartImplCopyWith( + _$ThinkingPartImpl value, $Res Function(_$ThinkingPartImpl) then) = + __$$ThinkingPartImplCopyWithImpl<$Res>; + @useResult + $Res call({String content}); +} + +/// @nodoc +class __$$ThinkingPartImplCopyWithImpl<$Res> + extends _$MessagePartCopyWithImpl<$Res, _$ThinkingPartImpl> + implements _$$ThinkingPartImplCopyWith<$Res> { + __$$ThinkingPartImplCopyWithImpl( + _$ThinkingPartImpl _value, $Res Function(_$ThinkingPartImpl) _then) + : super(_value, _then); + + /// Create a copy of MessagePart + /// with the given fields replaced by the non-null parameter values. + @pragma('vm:prefer-inline') + @override + $Res call({ + Object? content = null, + }) { + return _then(_$ThinkingPartImpl( + content: null == content + ? _value.content + : content // ignore: cast_nullable_to_non_nullable + as String, + )); + } +} + +/// @nodoc +@JsonSerializable() +class _$ThinkingPartImpl implements ThinkingPart { + const _$ThinkingPartImpl({required this.content, final String? $type}) + : $type = $type ?? 'thinking'; + + factory _$ThinkingPartImpl.fromJson(Map json) => + _$$ThinkingPartImplFromJson(json); + + @override + final String content; + + @JsonKey(name: 'runtimeType') + final String $type; + + @override + String toString() { + return 'MessagePart.thinking(content: $content)'; + } + + @override + bool operator ==(Object other) { + return identical(this, other) || + (other.runtimeType == runtimeType && + other is _$ThinkingPartImpl && + (identical(other.content, content) || other.content == content)); + } + + @JsonKey(includeFromJson: false, includeToJson: false) + @override + int get hashCode => Object.hash(runtimeType, content); + + /// Create a copy of MessagePart + /// with the given fields replaced by the non-null parameter values. + @JsonKey(includeFromJson: false, includeToJson: false) + @override + @pragma('vm:prefer-inline') + _$$ThinkingPartImplCopyWith<_$ThinkingPartImpl> get copyWith => + __$$ThinkingPartImplCopyWithImpl<_$ThinkingPartImpl>(this, _$identity); + + @override + @optionalTypeArgs + TResult when({ + required TResult Function(String content) text, + required TResult Function( + String tool, Map params, String? id) + toolUse, + required TResult Function(String toolCallId, ToolResult result) toolResult, + required TResult Function(String content) thinking, + }) { + return thinking(content); + } + + @override + @optionalTypeArgs + TResult? whenOrNull({ + TResult? Function(String content)? text, + TResult? Function(String tool, Map params, String? id)? + toolUse, + TResult? Function(String toolCallId, ToolResult result)? toolResult, + TResult? Function(String content)? thinking, + }) { + return thinking?.call(content); + } + + @override + @optionalTypeArgs + TResult maybeWhen({ + TResult Function(String content)? text, + TResult Function(String tool, Map params, String? id)? + toolUse, + TResult Function(String toolCallId, ToolResult result)? toolResult, + TResult Function(String content)? thinking, + required TResult orElse(), + }) { + if (thinking != null) { + return thinking(content); + } + return orElse(); + } + + @override + @optionalTypeArgs + TResult map({ + required TResult Function(TextPart value) text, + required TResult Function(ToolUsePart value) toolUse, + required TResult Function(ToolResultPart value) toolResult, + required TResult Function(ThinkingPart value) thinking, + }) { + return thinking(this); + } + + @override + @optionalTypeArgs + TResult? mapOrNull({ + TResult? Function(TextPart value)? text, + TResult? Function(ToolUsePart value)? toolUse, + TResult? Function(ToolResultPart value)? toolResult, + TResult? Function(ThinkingPart value)? thinking, + }) { + return thinking?.call(this); + } + + @override + @optionalTypeArgs + TResult maybeMap({ + TResult Function(TextPart value)? text, + TResult Function(ToolUsePart value)? toolUse, + TResult Function(ToolResultPart value)? toolResult, + TResult Function(ThinkingPart value)? thinking, + required TResult orElse(), + }) { + if (thinking != null) { + return thinking(this); + } + return orElse(); + } + + @override + Map toJson() { + return _$$ThinkingPartImplToJson( + this, + ); + } +} + +abstract class ThinkingPart implements MessagePart { + const factory ThinkingPart({required final String content}) = + _$ThinkingPartImpl; + + factory ThinkingPart.fromJson(Map json) = + _$ThinkingPartImpl.fromJson; + + String get content; + + /// Create a copy of MessagePart + /// with the given fields replaced by the non-null parameter values. + @JsonKey(includeFromJson: false, includeToJson: false) + _$$ThinkingPartImplCopyWith<_$ThinkingPartImpl> get copyWith => + throw _privateConstructorUsedError; +} + +ToolResult _$ToolResultFromJson(Map json) { + return _ToolResult.fromJson(json); +} + +/// @nodoc +mixin _$ToolResult { + bool get success => throw _privateConstructorUsedError; + String get content => throw _privateConstructorUsedError; + Map? get metadata => throw _privateConstructorUsedError; + String? get error => throw _privateConstructorUsedError; + int? get durationMs => throw _privateConstructorUsedError; + + /// Serializes this ToolResult to a JSON map. + Map toJson() => throw _privateConstructorUsedError; + + /// Create a copy of ToolResult + /// with the given fields replaced by the non-null parameter values. + @JsonKey(includeFromJson: false, includeToJson: false) + $ToolResultCopyWith get copyWith => + throw _privateConstructorUsedError; +} + +/// @nodoc +abstract class $ToolResultCopyWith<$Res> { + factory $ToolResultCopyWith( + ToolResult value, $Res Function(ToolResult) then) = + _$ToolResultCopyWithImpl<$Res, ToolResult>; + @useResult + $Res call( + {bool success, + String content, + Map? metadata, + String? error, + int? durationMs}); +} + +/// @nodoc +class _$ToolResultCopyWithImpl<$Res, $Val extends ToolResult> + implements $ToolResultCopyWith<$Res> { + _$ToolResultCopyWithImpl(this._value, this._then); + + // ignore: unused_field + final $Val _value; + // ignore: unused_field + final $Res Function($Val) _then; + + /// Create a copy of ToolResult + /// with the given fields replaced by the non-null parameter values. + @pragma('vm:prefer-inline') + @override + $Res call({ + Object? success = null, + Object? content = null, + Object? metadata = freezed, + Object? error = freezed, + Object? durationMs = freezed, + }) { + return _then(_value.copyWith( + success: null == success + ? _value.success + : success // ignore: cast_nullable_to_non_nullable + as bool, + content: null == content + ? _value.content + : content // ignore: cast_nullable_to_non_nullable + as String, + metadata: freezed == metadata + ? _value.metadata + : metadata // ignore: cast_nullable_to_non_nullable + as Map?, + error: freezed == error + ? _value.error + : error // ignore: cast_nullable_to_non_nullable + as String?, + durationMs: freezed == durationMs + ? _value.durationMs + : durationMs // ignore: cast_nullable_to_non_nullable + as int?, + ) as $Val); + } +} + +/// @nodoc +abstract class _$$ToolResultImplCopyWith<$Res> + implements $ToolResultCopyWith<$Res> { + factory _$$ToolResultImplCopyWith( + _$ToolResultImpl value, $Res Function(_$ToolResultImpl) then) = + __$$ToolResultImplCopyWithImpl<$Res>; + @override + @useResult + $Res call( + {bool success, + String content, + Map? metadata, + String? error, + int? durationMs}); +} + +/// @nodoc +class __$$ToolResultImplCopyWithImpl<$Res> + extends _$ToolResultCopyWithImpl<$Res, _$ToolResultImpl> + implements _$$ToolResultImplCopyWith<$Res> { + __$$ToolResultImplCopyWithImpl( + _$ToolResultImpl _value, $Res Function(_$ToolResultImpl) _then) + : super(_value, _then); + + /// Create a copy of ToolResult + /// with the given fields replaced by the non-null parameter values. + @pragma('vm:prefer-inline') + @override + $Res call({ + Object? success = null, + Object? content = null, + Object? metadata = freezed, + Object? error = freezed, + Object? durationMs = freezed, + }) { + return _then(_$ToolResultImpl( + success: null == success + ? _value.success + : success // ignore: cast_nullable_to_non_nullable + as bool, + content: null == content + ? _value.content + : content // ignore: cast_nullable_to_non_nullable + as String, + metadata: freezed == metadata + ? _value._metadata + : metadata // ignore: cast_nullable_to_non_nullable + as Map?, + error: freezed == error + ? _value.error + : error // ignore: cast_nullable_to_non_nullable + as String?, + durationMs: freezed == durationMs + ? _value.durationMs + : durationMs // ignore: cast_nullable_to_non_nullable + as int?, + )); + } +} + +/// @nodoc +@JsonSerializable() +class _$ToolResultImpl implements _ToolResult { + const _$ToolResultImpl( + {required this.success, + required this.content, + final Map? metadata, + this.error, + this.durationMs}) + : _metadata = metadata; + + factory _$ToolResultImpl.fromJson(Map json) => + _$$ToolResultImplFromJson(json); + + @override + final bool success; + @override + final String content; + final Map? _metadata; + @override + Map? get metadata { + final value = _metadata; + if (value == null) return null; + if (_metadata is EqualUnmodifiableMapView) return _metadata; + // ignore: implicit_dynamic_type + return EqualUnmodifiableMapView(value); + } + + @override + final String? error; + @override + final int? durationMs; + + @override + String toString() { + return 'ToolResult(success: $success, content: $content, metadata: $metadata, error: $error, durationMs: $durationMs)'; + } + + @override + bool operator ==(Object other) { + return identical(this, other) || + (other.runtimeType == runtimeType && + other is _$ToolResultImpl && + (identical(other.success, success) || other.success == success) && + (identical(other.content, content) || other.content == content) && + const DeepCollectionEquality().equals(other._metadata, _metadata) && + (identical(other.error, error) || other.error == error) && + (identical(other.durationMs, durationMs) || + other.durationMs == durationMs)); + } + + @JsonKey(includeFromJson: false, includeToJson: false) + @override + int get hashCode => Object.hash(runtimeType, success, content, + const DeepCollectionEquality().hash(_metadata), error, durationMs); + + /// Create a copy of ToolResult + /// with the given fields replaced by the non-null parameter values. + @JsonKey(includeFromJson: false, includeToJson: false) + @override + @pragma('vm:prefer-inline') + _$$ToolResultImplCopyWith<_$ToolResultImpl> get copyWith => + __$$ToolResultImplCopyWithImpl<_$ToolResultImpl>(this, _$identity); + + @override + Map toJson() { + return _$$ToolResultImplToJson( + this, + ); + } +} + +abstract class _ToolResult implements ToolResult { + const factory _ToolResult( + {required final bool success, + required final String content, + final Map? metadata, + final String? error, + final int? durationMs}) = _$ToolResultImpl; + + factory _ToolResult.fromJson(Map json) = + _$ToolResultImpl.fromJson; + + @override + bool get success; + @override + String get content; + @override + Map? get metadata; + @override + String? get error; + @override + int? get durationMs; + + /// Create a copy of ToolResult + /// with the given fields replaced by the non-null parameter values. + @override + @JsonKey(includeFromJson: false, includeToJson: false) + _$$ToolResultImplCopyWith<_$ToolResultImpl> get copyWith => + throw _privateConstructorUsedError; +} + +ToolCall _$ToolCallFromJson(Map json) { + return _ToolCall.fromJson(json); +} + +/// @nodoc +mixin _$ToolCall { + String get id => throw _privateConstructorUsedError; + String get sessionId => throw _privateConstructorUsedError; + String get tool => throw _privateConstructorUsedError; + Map get params => throw _privateConstructorUsedError; + String? get description => throw _privateConstructorUsedError; + String? get reasoning => throw _privateConstructorUsedError; + RiskLevel get riskLevel => throw _privateConstructorUsedError; + ApprovalDecision get decision => throw _privateConstructorUsedError; + String? get modifications => throw _privateConstructorUsedError; + Map? get result => throw _privateConstructorUsedError; + DateTime get createdAt => throw _privateConstructorUsedError; + DateTime? get decidedAt => throw _privateConstructorUsedError; + + /// Serializes this ToolCall to a JSON map. + Map toJson() => throw _privateConstructorUsedError; + + /// Create a copy of ToolCall + /// with the given fields replaced by the non-null parameter values. + @JsonKey(includeFromJson: false, includeToJson: false) + $ToolCallCopyWith get copyWith => + throw _privateConstructorUsedError; +} + +/// @nodoc +abstract class $ToolCallCopyWith<$Res> { + factory $ToolCallCopyWith(ToolCall value, $Res Function(ToolCall) then) = + _$ToolCallCopyWithImpl<$Res, ToolCall>; + @useResult + $Res call( + {String id, + String sessionId, + String tool, + Map params, + String? description, + String? reasoning, + RiskLevel riskLevel, + ApprovalDecision decision, + String? modifications, + Map? result, + DateTime createdAt, + DateTime? decidedAt}); +} + +/// @nodoc +class _$ToolCallCopyWithImpl<$Res, $Val extends ToolCall> + implements $ToolCallCopyWith<$Res> { + _$ToolCallCopyWithImpl(this._value, this._then); + + // ignore: unused_field + final $Val _value; + // ignore: unused_field + final $Res Function($Val) _then; + + /// Create a copy of ToolCall + /// with the given fields replaced by the non-null parameter values. + @pragma('vm:prefer-inline') + @override + $Res call({ + Object? id = null, + Object? sessionId = null, + Object? tool = null, + Object? params = null, + Object? description = freezed, + Object? reasoning = freezed, + Object? riskLevel = null, + Object? decision = null, + Object? modifications = freezed, + Object? result = freezed, + Object? createdAt = null, + Object? decidedAt = freezed, + }) { + return _then(_value.copyWith( + id: null == id + ? _value.id + : id // ignore: cast_nullable_to_non_nullable + as String, + sessionId: null == sessionId + ? _value.sessionId + : sessionId // ignore: cast_nullable_to_non_nullable + as String, + tool: null == tool + ? _value.tool + : tool // ignore: cast_nullable_to_non_nullable + as String, + params: null == params + ? _value.params + : params // ignore: cast_nullable_to_non_nullable + as Map, + description: freezed == description + ? _value.description + : description // ignore: cast_nullable_to_non_nullable + as String?, + reasoning: freezed == reasoning + ? _value.reasoning + : reasoning // ignore: cast_nullable_to_non_nullable + as String?, + riskLevel: null == riskLevel + ? _value.riskLevel + : riskLevel // ignore: cast_nullable_to_non_nullable + as RiskLevel, + decision: null == decision + ? _value.decision + : decision // ignore: cast_nullable_to_non_nullable + as ApprovalDecision, + modifications: freezed == modifications + ? _value.modifications + : modifications // ignore: cast_nullable_to_non_nullable + as String?, + result: freezed == result + ? _value.result + : result // ignore: cast_nullable_to_non_nullable + as Map?, + createdAt: null == createdAt + ? _value.createdAt + : createdAt // ignore: cast_nullable_to_non_nullable + as DateTime, + decidedAt: freezed == decidedAt + ? _value.decidedAt + : decidedAt // ignore: cast_nullable_to_non_nullable + as DateTime?, + ) as $Val); + } +} + +/// @nodoc +abstract class _$$ToolCallImplCopyWith<$Res> + implements $ToolCallCopyWith<$Res> { + factory _$$ToolCallImplCopyWith( + _$ToolCallImpl value, $Res Function(_$ToolCallImpl) then) = + __$$ToolCallImplCopyWithImpl<$Res>; + @override + @useResult + $Res call( + {String id, + String sessionId, + String tool, + Map params, + String? description, + String? reasoning, + RiskLevel riskLevel, + ApprovalDecision decision, + String? modifications, + Map? result, + DateTime createdAt, + DateTime? decidedAt}); +} + +/// @nodoc +class __$$ToolCallImplCopyWithImpl<$Res> + extends _$ToolCallCopyWithImpl<$Res, _$ToolCallImpl> + implements _$$ToolCallImplCopyWith<$Res> { + __$$ToolCallImplCopyWithImpl( + _$ToolCallImpl _value, $Res Function(_$ToolCallImpl) _then) + : super(_value, _then); + + /// Create a copy of ToolCall + /// with the given fields replaced by the non-null parameter values. + @pragma('vm:prefer-inline') + @override + $Res call({ + Object? id = null, + Object? sessionId = null, + Object? tool = null, + Object? params = null, + Object? description = freezed, + Object? reasoning = freezed, + Object? riskLevel = null, + Object? decision = null, + Object? modifications = freezed, + Object? result = freezed, + Object? createdAt = null, + Object? decidedAt = freezed, + }) { + return _then(_$ToolCallImpl( + id: null == id + ? _value.id + : id // ignore: cast_nullable_to_non_nullable + as String, + sessionId: null == sessionId + ? _value.sessionId + : sessionId // ignore: cast_nullable_to_non_nullable + as String, + tool: null == tool + ? _value.tool + : tool // ignore: cast_nullable_to_non_nullable + as String, + params: null == params + ? _value._params + : params // ignore: cast_nullable_to_non_nullable + as Map, + description: freezed == description + ? _value.description + : description // ignore: cast_nullable_to_non_nullable + as String?, + reasoning: freezed == reasoning + ? _value.reasoning + : reasoning // ignore: cast_nullable_to_non_nullable + as String?, + riskLevel: null == riskLevel + ? _value.riskLevel + : riskLevel // ignore: cast_nullable_to_non_nullable + as RiskLevel, + decision: null == decision + ? _value.decision + : decision // ignore: cast_nullable_to_non_nullable + as ApprovalDecision, + modifications: freezed == modifications + ? _value.modifications + : modifications // ignore: cast_nullable_to_non_nullable + as String?, + result: freezed == result + ? _value._result + : result // ignore: cast_nullable_to_non_nullable + as Map?, + createdAt: null == createdAt + ? _value.createdAt + : createdAt // ignore: cast_nullable_to_non_nullable + as DateTime, + decidedAt: freezed == decidedAt + ? _value.decidedAt + : decidedAt // ignore: cast_nullable_to_non_nullable + as DateTime?, + )); + } +} + +/// @nodoc +@JsonSerializable() +class _$ToolCallImpl implements _ToolCall { + const _$ToolCallImpl( + {required this.id, + required this.sessionId, + required this.tool, + required final Map params, + this.description, + this.reasoning, + this.riskLevel = RiskLevel.low, + this.decision = ApprovalDecision.pending, + this.modifications, + final Map? result, + required this.createdAt, + this.decidedAt}) + : _params = params, + _result = result; + + factory _$ToolCallImpl.fromJson(Map json) => + _$$ToolCallImplFromJson(json); + + @override + final String id; + @override + final String sessionId; + @override + final String tool; + final Map _params; + @override + Map get params { + if (_params is EqualUnmodifiableMapView) return _params; + // ignore: implicit_dynamic_type + return EqualUnmodifiableMapView(_params); + } + + @override + final String? description; + @override + final String? reasoning; + @override + @JsonKey() + final RiskLevel riskLevel; + @override + @JsonKey() + final ApprovalDecision decision; + @override + final String? modifications; + final Map? _result; + @override + Map? get result { + final value = _result; + if (value == null) return null; + if (_result is EqualUnmodifiableMapView) return _result; + // ignore: implicit_dynamic_type + return EqualUnmodifiableMapView(value); + } + + @override + final DateTime createdAt; + @override + final DateTime? decidedAt; + + @override + String toString() { + return 'ToolCall(id: $id, sessionId: $sessionId, tool: $tool, params: $params, description: $description, reasoning: $reasoning, riskLevel: $riskLevel, decision: $decision, modifications: $modifications, result: $result, createdAt: $createdAt, decidedAt: $decidedAt)'; + } + + @override + bool operator ==(Object other) { + return identical(this, other) || + (other.runtimeType == runtimeType && + other is _$ToolCallImpl && + (identical(other.id, id) || other.id == id) && + (identical(other.sessionId, sessionId) || + other.sessionId == sessionId) && + (identical(other.tool, tool) || other.tool == tool) && + const DeepCollectionEquality().equals(other._params, _params) && + (identical(other.description, description) || + other.description == description) && + (identical(other.reasoning, reasoning) || + other.reasoning == reasoning) && + (identical(other.riskLevel, riskLevel) || + other.riskLevel == riskLevel) && + (identical(other.decision, decision) || + other.decision == decision) && + (identical(other.modifications, modifications) || + other.modifications == modifications) && + const DeepCollectionEquality().equals(other._result, _result) && + (identical(other.createdAt, createdAt) || + other.createdAt == createdAt) && + (identical(other.decidedAt, decidedAt) || + other.decidedAt == decidedAt)); + } + + @JsonKey(includeFromJson: false, includeToJson: false) + @override + int get hashCode => Object.hash( + runtimeType, + id, + sessionId, + tool, + const DeepCollectionEquality().hash(_params), + description, + reasoning, + riskLevel, + decision, + modifications, + const DeepCollectionEquality().hash(_result), + createdAt, + decidedAt); + + /// Create a copy of ToolCall + /// with the given fields replaced by the non-null parameter values. + @JsonKey(includeFromJson: false, includeToJson: false) + @override + @pragma('vm:prefer-inline') + _$$ToolCallImplCopyWith<_$ToolCallImpl> get copyWith => + __$$ToolCallImplCopyWithImpl<_$ToolCallImpl>(this, _$identity); + + @override + Map toJson() { + return _$$ToolCallImplToJson( + this, + ); + } +} + +abstract class _ToolCall implements ToolCall { + const factory _ToolCall( + {required final String id, + required final String sessionId, + required final String tool, + required final Map params, + final String? description, + final String? reasoning, + final RiskLevel riskLevel, + final ApprovalDecision decision, + final String? modifications, + final Map? result, + required final DateTime createdAt, + final DateTime? decidedAt}) = _$ToolCallImpl; + + factory _ToolCall.fromJson(Map json) = + _$ToolCallImpl.fromJson; + + @override + String get id; + @override + String get sessionId; + @override + String get tool; + @override + Map get params; + @override + String? get description; + @override + String? get reasoning; + @override + RiskLevel get riskLevel; + @override + ApprovalDecision get decision; + @override + String? get modifications; + @override + Map? get result; + @override + DateTime get createdAt; + @override + DateTime? get decidedAt; + + /// Create a copy of ToolCall + /// with the given fields replaced by the non-null parameter values. + @override + @JsonKey(includeFromJson: false, includeToJson: false) + _$$ToolCallImplCopyWith<_$ToolCallImpl> get copyWith => + throw _privateConstructorUsedError; +} + +Message _$MessageFromJson(Map json) { + return _Message.fromJson(json); +} + +/// @nodoc +mixin _$Message { + String get id => throw _privateConstructorUsedError; + String get sessionId => throw _privateConstructorUsedError; + MessageRole get role => throw _privateConstructorUsedError; + String get content => throw _privateConstructorUsedError; + MessageType get type => throw _privateConstructorUsedError; + List get parts => throw _privateConstructorUsedError; + Map? get metadata => throw _privateConstructorUsedError; + DateTime get createdAt => throw _privateConstructorUsedError; + DateTime? get updatedAt => throw _privateConstructorUsedError; + bool get synced => throw _privateConstructorUsedError; + + /// Serializes this Message to a JSON map. + Map toJson() => throw _privateConstructorUsedError; + + /// Create a copy of Message + /// with the given fields replaced by the non-null parameter values. + @JsonKey(includeFromJson: false, includeToJson: false) + $MessageCopyWith get copyWith => throw _privateConstructorUsedError; +} + +/// @nodoc +abstract class $MessageCopyWith<$Res> { + factory $MessageCopyWith(Message value, $Res Function(Message) then) = + _$MessageCopyWithImpl<$Res, Message>; + @useResult + $Res call( + {String id, + String sessionId, + MessageRole role, + String content, + MessageType type, + List parts, + Map? metadata, + DateTime createdAt, + DateTime? updatedAt, + bool synced}); +} + +/// @nodoc +class _$MessageCopyWithImpl<$Res, $Val extends Message> + implements $MessageCopyWith<$Res> { + _$MessageCopyWithImpl(this._value, this._then); + + // ignore: unused_field + final $Val _value; + // ignore: unused_field + final $Res Function($Val) _then; + + /// Create a copy of Message + /// with the given fields replaced by the non-null parameter values. + @pragma('vm:prefer-inline') + @override + $Res call({ + Object? id = null, + Object? sessionId = null, + Object? role = null, + Object? content = null, + Object? type = null, + Object? parts = null, + Object? metadata = freezed, + Object? createdAt = null, + Object? updatedAt = freezed, + Object? synced = null, + }) { + return _then(_value.copyWith( + id: null == id + ? _value.id + : id // ignore: cast_nullable_to_non_nullable + as String, + sessionId: null == sessionId + ? _value.sessionId + : sessionId // ignore: cast_nullable_to_non_nullable + as String, + role: null == role + ? _value.role + : role // ignore: cast_nullable_to_non_nullable + as MessageRole, + content: null == content + ? _value.content + : content // ignore: cast_nullable_to_non_nullable + as String, + type: null == type + ? _value.type + : type // ignore: cast_nullable_to_non_nullable + as MessageType, + parts: null == parts + ? _value.parts + : parts // ignore: cast_nullable_to_non_nullable + as List, + metadata: freezed == metadata + ? _value.metadata + : metadata // ignore: cast_nullable_to_non_nullable + as Map?, + createdAt: null == createdAt + ? _value.createdAt + : createdAt // ignore: cast_nullable_to_non_nullable + as DateTime, + updatedAt: freezed == updatedAt + ? _value.updatedAt + : updatedAt // ignore: cast_nullable_to_non_nullable + as DateTime?, + synced: null == synced + ? _value.synced + : synced // ignore: cast_nullable_to_non_nullable + as bool, + ) as $Val); + } +} + +/// @nodoc +abstract class _$$MessageImplCopyWith<$Res> implements $MessageCopyWith<$Res> { + factory _$$MessageImplCopyWith( + _$MessageImpl value, $Res Function(_$MessageImpl) then) = + __$$MessageImplCopyWithImpl<$Res>; + @override + @useResult + $Res call( + {String id, + String sessionId, + MessageRole role, + String content, + MessageType type, + List parts, + Map? metadata, + DateTime createdAt, + DateTime? updatedAt, + bool synced}); +} + +/// @nodoc +class __$$MessageImplCopyWithImpl<$Res> + extends _$MessageCopyWithImpl<$Res, _$MessageImpl> + implements _$$MessageImplCopyWith<$Res> { + __$$MessageImplCopyWithImpl( + _$MessageImpl _value, $Res Function(_$MessageImpl) _then) + : super(_value, _then); + + /// Create a copy of Message + /// with the given fields replaced by the non-null parameter values. + @pragma('vm:prefer-inline') + @override + $Res call({ + Object? id = null, + Object? sessionId = null, + Object? role = null, + Object? content = null, + Object? type = null, + Object? parts = null, + Object? metadata = freezed, + Object? createdAt = null, + Object? updatedAt = freezed, + Object? synced = null, + }) { + return _then(_$MessageImpl( + id: null == id + ? _value.id + : id // ignore: cast_nullable_to_non_nullable + as String, + sessionId: null == sessionId + ? _value.sessionId + : sessionId // ignore: cast_nullable_to_non_nullable + as String, + role: null == role + ? _value.role + : role // ignore: cast_nullable_to_non_nullable + as MessageRole, + content: null == content + ? _value.content + : content // ignore: cast_nullable_to_non_nullable + as String, + type: null == type + ? _value.type + : type // ignore: cast_nullable_to_non_nullable + as MessageType, + parts: null == parts + ? _value._parts + : parts // ignore: cast_nullable_to_non_nullable + as List, + metadata: freezed == metadata + ? _value._metadata + : metadata // ignore: cast_nullable_to_non_nullable + as Map?, + createdAt: null == createdAt + ? _value.createdAt + : createdAt // ignore: cast_nullable_to_non_nullable + as DateTime, + updatedAt: freezed == updatedAt + ? _value.updatedAt + : updatedAt // ignore: cast_nullable_to_non_nullable + as DateTime?, + synced: null == synced + ? _value.synced + : synced // ignore: cast_nullable_to_non_nullable + as bool, + )); + } +} + +/// @nodoc +@JsonSerializable() +class _$MessageImpl implements _Message { + const _$MessageImpl( + {required this.id, + required this.sessionId, + required this.role, + required this.content, + required this.type, + required final List parts, + final Map? metadata, + required this.createdAt, + this.updatedAt, + this.synced = true}) + : _parts = parts, + _metadata = metadata; + + factory _$MessageImpl.fromJson(Map json) => + _$$MessageImplFromJson(json); + + @override + final String id; + @override + final String sessionId; + @override + final MessageRole role; + @override + final String content; + @override + final MessageType type; + final List _parts; + @override + List get parts { + if (_parts is EqualUnmodifiableListView) return _parts; + // ignore: implicit_dynamic_type + return EqualUnmodifiableListView(_parts); + } + + final Map? _metadata; + @override + Map? get metadata { + final value = _metadata; + if (value == null) return null; + if (_metadata is EqualUnmodifiableMapView) return _metadata; + // ignore: implicit_dynamic_type + return EqualUnmodifiableMapView(value); + } + + @override + final DateTime createdAt; + @override + final DateTime? updatedAt; + @override + @JsonKey() + final bool synced; + + @override + String toString() { + return 'Message(id: $id, sessionId: $sessionId, role: $role, content: $content, type: $type, parts: $parts, metadata: $metadata, createdAt: $createdAt, updatedAt: $updatedAt, synced: $synced)'; + } + + @override + bool operator ==(Object other) { + return identical(this, other) || + (other.runtimeType == runtimeType && + other is _$MessageImpl && + (identical(other.id, id) || other.id == id) && + (identical(other.sessionId, sessionId) || + other.sessionId == sessionId) && + (identical(other.role, role) || other.role == role) && + (identical(other.content, content) || other.content == content) && + (identical(other.type, type) || other.type == type) && + const DeepCollectionEquality().equals(other._parts, _parts) && + const DeepCollectionEquality().equals(other._metadata, _metadata) && + (identical(other.createdAt, createdAt) || + other.createdAt == createdAt) && + (identical(other.updatedAt, updatedAt) || + other.updatedAt == updatedAt) && + (identical(other.synced, synced) || other.synced == synced)); + } + + @JsonKey(includeFromJson: false, includeToJson: false) + @override + int get hashCode => Object.hash( + runtimeType, + id, + sessionId, + role, + content, + type, + const DeepCollectionEquality().hash(_parts), + const DeepCollectionEquality().hash(_metadata), + createdAt, + updatedAt, + synced); + + /// Create a copy of Message + /// with the given fields replaced by the non-null parameter values. + @JsonKey(includeFromJson: false, includeToJson: false) + @override + @pragma('vm:prefer-inline') + _$$MessageImplCopyWith<_$MessageImpl> get copyWith => + __$$MessageImplCopyWithImpl<_$MessageImpl>(this, _$identity); + + @override + Map toJson() { + return _$$MessageImplToJson( + this, + ); + } +} + +abstract class _Message implements Message { + const factory _Message( + {required final String id, + required final String sessionId, + required final MessageRole role, + required final String content, + required final MessageType type, + required final List parts, + final Map? metadata, + required final DateTime createdAt, + final DateTime? updatedAt, + final bool synced}) = _$MessageImpl; + + factory _Message.fromJson(Map json) = _$MessageImpl.fromJson; + + @override + String get id; + @override + String get sessionId; + @override + MessageRole get role; + @override + String get content; + @override + MessageType get type; + @override + List get parts; + @override + Map? get metadata; + @override + DateTime get createdAt; + @override + DateTime? get updatedAt; + @override + bool get synced; + + /// Create a copy of Message + /// with the given fields replaced by the non-null parameter values. + @override + @JsonKey(includeFromJson: false, includeToJson: false) + _$$MessageImplCopyWith<_$MessageImpl> get copyWith => + throw _privateConstructorUsedError; +} diff --git a/apps/mobile/lib/core/models/message_models.g.dart b/apps/mobile/lib/core/models/message_models.g.dart new file mode 100644 index 0000000..e25fc1c --- /dev/null +++ b/apps/mobile/lib/core/models/message_models.g.dart @@ -0,0 +1,176 @@ +// GENERATED CODE - DO NOT MODIFY BY HAND + +part of 'message_models.dart'; + +// ************************************************************************** +// JsonSerializableGenerator +// ************************************************************************** + +_$TextPartImpl _$$TextPartImplFromJson(Map json) => + _$TextPartImpl( + content: json['content'] as String, + $type: json['runtimeType'] as String?, + ); + +Map _$$TextPartImplToJson(_$TextPartImpl instance) => + { + 'content': instance.content, + 'runtimeType': instance.$type, + }; + +_$ToolUsePartImpl _$$ToolUsePartImplFromJson(Map json) => + _$ToolUsePartImpl( + tool: json['tool'] as String, + params: json['params'] as Map, + id: json['id'] as String?, + $type: json['runtimeType'] as String?, + ); + +Map _$$ToolUsePartImplToJson(_$ToolUsePartImpl instance) => + { + 'tool': instance.tool, + 'params': instance.params, + 'id': instance.id, + 'runtimeType': instance.$type, + }; + +_$ToolResultPartImpl _$$ToolResultPartImplFromJson(Map json) => + _$ToolResultPartImpl( + toolCallId: json['toolCallId'] as String, + result: ToolResult.fromJson(json['result'] as Map), + $type: json['runtimeType'] as String?, + ); + +Map _$$ToolResultPartImplToJson( + _$ToolResultPartImpl instance) => + { + 'toolCallId': instance.toolCallId, + 'result': instance.result, + 'runtimeType': instance.$type, + }; + +_$ThinkingPartImpl _$$ThinkingPartImplFromJson(Map json) => + _$ThinkingPartImpl( + content: json['content'] as String, + $type: json['runtimeType'] as String?, + ); + +Map _$$ThinkingPartImplToJson(_$ThinkingPartImpl instance) => + { + 'content': instance.content, + 'runtimeType': instance.$type, + }; + +_$ToolResultImpl _$$ToolResultImplFromJson(Map json) => + _$ToolResultImpl( + success: json['success'] as bool, + content: json['content'] as String, + metadata: json['metadata'] as Map?, + error: json['error'] as String?, + durationMs: (json['durationMs'] as num?)?.toInt(), + ); + +Map _$$ToolResultImplToJson(_$ToolResultImpl instance) => + { + 'success': instance.success, + 'content': instance.content, + 'metadata': instance.metadata, + 'error': instance.error, + 'durationMs': instance.durationMs, + }; + +_$ToolCallImpl _$$ToolCallImplFromJson(Map json) => + _$ToolCallImpl( + id: json['id'] as String, + sessionId: json['sessionId'] as String, + tool: json['tool'] as String, + params: json['params'] as Map, + description: json['description'] as String?, + reasoning: json['reasoning'] as String?, + riskLevel: $enumDecodeNullable(_$RiskLevelEnumMap, json['riskLevel']) ?? + RiskLevel.low, + decision: + $enumDecodeNullable(_$ApprovalDecisionEnumMap, json['decision']) ?? + ApprovalDecision.pending, + modifications: json['modifications'] as String?, + result: json['result'] as Map?, + createdAt: DateTime.parse(json['createdAt'] as String), + decidedAt: json['decidedAt'] == null + ? null + : DateTime.parse(json['decidedAt'] as String), + ); + +Map _$$ToolCallImplToJson(_$ToolCallImpl instance) => + { + 'id': instance.id, + 'sessionId': instance.sessionId, + 'tool': instance.tool, + 'params': instance.params, + 'description': instance.description, + 'reasoning': instance.reasoning, + 'riskLevel': _$RiskLevelEnumMap[instance.riskLevel]!, + 'decision': _$ApprovalDecisionEnumMap[instance.decision]!, + 'modifications': instance.modifications, + 'result': instance.result, + 'createdAt': instance.createdAt.toIso8601String(), + 'decidedAt': instance.decidedAt?.toIso8601String(), + }; + +const _$RiskLevelEnumMap = { + RiskLevel.low: 'low', + RiskLevel.medium: 'medium', + RiskLevel.high: 'high', + RiskLevel.critical: 'critical', +}; + +const _$ApprovalDecisionEnumMap = { + ApprovalDecision.pending: 'pending', + ApprovalDecision.approved: 'approved', + ApprovalDecision.rejected: 'rejected', + ApprovalDecision.modified: 'modified', +}; + +_$MessageImpl _$$MessageImplFromJson(Map json) => + _$MessageImpl( + id: json['id'] as String, + sessionId: json['sessionId'] as String, + role: $enumDecode(_$MessageRoleEnumMap, json['role']), + content: json['content'] as String, + type: $enumDecode(_$MessageTypeEnumMap, json['type']), + parts: (json['parts'] as List) + .map((e) => MessagePart.fromJson(e as Map)) + .toList(), + metadata: json['metadata'] as Map?, + createdAt: DateTime.parse(json['createdAt'] as String), + updatedAt: json['updatedAt'] == null + ? null + : DateTime.parse(json['updatedAt'] as String), + synced: json['synced'] as bool? ?? true, + ); + +Map _$$MessageImplToJson(_$MessageImpl instance) => + { + 'id': instance.id, + 'sessionId': instance.sessionId, + 'role': _$MessageRoleEnumMap[instance.role]!, + 'content': instance.content, + 'type': _$MessageTypeEnumMap[instance.type]!, + 'parts': instance.parts, + 'metadata': instance.metadata, + 'createdAt': instance.createdAt.toIso8601String(), + 'updatedAt': instance.updatedAt?.toIso8601String(), + 'synced': instance.synced, + }; + +const _$MessageRoleEnumMap = { + MessageRole.user: 'user', + MessageRole.agent: 'agent', + MessageRole.system: 'system', +}; + +const _$MessageTypeEnumMap = { + MessageType.text: 'text', + MessageType.toolCall: 'toolCall', + MessageType.toolResult: 'toolResult', + MessageType.system: 'system', +}; diff --git a/apps/mobile/lib/core/models/models.dart b/apps/mobile/lib/core/models/models.dart new file mode 100644 index 0000000..737fc09 --- /dev/null +++ b/apps/mobile/lib/core/models/models.dart @@ -0,0 +1,7 @@ +export 'agent_models.dart'; +export 'file_models.dart'; +export 'git_models.dart'; +export 'hook_models.dart'; +export 'message_models.dart'; +export 'notification_models.dart'; +export 'session_models.dart'; diff --git a/apps/mobile/lib/core/models/notification_models.dart b/apps/mobile/lib/core/models/notification_models.dart new file mode 100644 index 0000000..0ffb7fb --- /dev/null +++ b/apps/mobile/lib/core/models/notification_models.dart @@ -0,0 +1,26 @@ +import 'package:freezed_annotation/freezed_annotation.dart'; + +part 'notification_models.freezed.dart'; +part 'notification_models.g.dart'; + +enum NotificationType { approvalRequired, taskComplete, error, info } + +enum NotificationPriority { low, normal, high } + +@freezed +class AppNotification with _$AppNotification { + const factory AppNotification({ + required String id, + String? sessionId, + required NotificationType type, + required String title, + required String body, + @Default(NotificationPriority.normal) NotificationPriority priority, + Map? data, + required DateTime timestamp, + @Default(false) bool isRead, + }) = _AppNotification; + + factory AppNotification.fromJson(Map json) => + _$AppNotificationFromJson(json); +} diff --git a/apps/mobile/lib/core/models/notification_models.freezed.dart b/apps/mobile/lib/core/models/notification_models.freezed.dart new file mode 100644 index 0000000..687dcec --- /dev/null +++ b/apps/mobile/lib/core/models/notification_models.freezed.dart @@ -0,0 +1,344 @@ +// coverage:ignore-file +// GENERATED CODE - DO NOT MODIFY BY HAND +// ignore_for_file: type=lint +// ignore_for_file: unused_element, deprecated_member_use, deprecated_member_use_from_same_package, use_function_type_syntax_for_parameters, unnecessary_const, avoid_init_to_null, invalid_override_different_default_values_named, prefer_expression_function_bodies, annotate_overrides, invalid_annotation_target, unnecessary_question_mark + +part of 'notification_models.dart'; + +// ************************************************************************** +// FreezedGenerator +// ************************************************************************** + +T _$identity(T value) => value; + +final _privateConstructorUsedError = UnsupportedError( + 'It seems like you constructed your class using `MyClass._()`. This constructor is only meant to be used by freezed and you are not supposed to need it nor use it.\nPlease check the documentation here for more information: https://github.com/rrousselGit/freezed#adding-getters-and-methods-to-our-models'); + +AppNotification _$AppNotificationFromJson(Map json) { + return _AppNotification.fromJson(json); +} + +/// @nodoc +mixin _$AppNotification { + String get id => throw _privateConstructorUsedError; + String? get sessionId => throw _privateConstructorUsedError; + NotificationType get type => throw _privateConstructorUsedError; + String get title => throw _privateConstructorUsedError; + String get body => throw _privateConstructorUsedError; + NotificationPriority get priority => throw _privateConstructorUsedError; + Map? get data => throw _privateConstructorUsedError; + DateTime get timestamp => throw _privateConstructorUsedError; + bool get isRead => throw _privateConstructorUsedError; + + /// Serializes this AppNotification to a JSON map. + Map toJson() => throw _privateConstructorUsedError; + + /// Create a copy of AppNotification + /// with the given fields replaced by the non-null parameter values. + @JsonKey(includeFromJson: false, includeToJson: false) + $AppNotificationCopyWith get copyWith => + throw _privateConstructorUsedError; +} + +/// @nodoc +abstract class $AppNotificationCopyWith<$Res> { + factory $AppNotificationCopyWith( + AppNotification value, $Res Function(AppNotification) then) = + _$AppNotificationCopyWithImpl<$Res, AppNotification>; + @useResult + $Res call( + {String id, + String? sessionId, + NotificationType type, + String title, + String body, + NotificationPriority priority, + Map? data, + DateTime timestamp, + bool isRead}); +} + +/// @nodoc +class _$AppNotificationCopyWithImpl<$Res, $Val extends AppNotification> + implements $AppNotificationCopyWith<$Res> { + _$AppNotificationCopyWithImpl(this._value, this._then); + + // ignore: unused_field + final $Val _value; + // ignore: unused_field + final $Res Function($Val) _then; + + /// Create a copy of AppNotification + /// with the given fields replaced by the non-null parameter values. + @pragma('vm:prefer-inline') + @override + $Res call({ + Object? id = null, + Object? sessionId = freezed, + Object? type = null, + Object? title = null, + Object? body = null, + Object? priority = null, + Object? data = freezed, + Object? timestamp = null, + Object? isRead = null, + }) { + return _then(_value.copyWith( + id: null == id + ? _value.id + : id // ignore: cast_nullable_to_non_nullable + as String, + sessionId: freezed == sessionId + ? _value.sessionId + : sessionId // ignore: cast_nullable_to_non_nullable + as String?, + type: null == type + ? _value.type + : type // ignore: cast_nullable_to_non_nullable + as NotificationType, + title: null == title + ? _value.title + : title // ignore: cast_nullable_to_non_nullable + as String, + body: null == body + ? _value.body + : body // ignore: cast_nullable_to_non_nullable + as String, + priority: null == priority + ? _value.priority + : priority // ignore: cast_nullable_to_non_nullable + as NotificationPriority, + data: freezed == data + ? _value.data + : data // ignore: cast_nullable_to_non_nullable + as Map?, + timestamp: null == timestamp + ? _value.timestamp + : timestamp // ignore: cast_nullable_to_non_nullable + as DateTime, + isRead: null == isRead + ? _value.isRead + : isRead // ignore: cast_nullable_to_non_nullable + as bool, + ) as $Val); + } +} + +/// @nodoc +abstract class _$$AppNotificationImplCopyWith<$Res> + implements $AppNotificationCopyWith<$Res> { + factory _$$AppNotificationImplCopyWith(_$AppNotificationImpl value, + $Res Function(_$AppNotificationImpl) then) = + __$$AppNotificationImplCopyWithImpl<$Res>; + @override + @useResult + $Res call( + {String id, + String? sessionId, + NotificationType type, + String title, + String body, + NotificationPriority priority, + Map? data, + DateTime timestamp, + bool isRead}); +} + +/// @nodoc +class __$$AppNotificationImplCopyWithImpl<$Res> + extends _$AppNotificationCopyWithImpl<$Res, _$AppNotificationImpl> + implements _$$AppNotificationImplCopyWith<$Res> { + __$$AppNotificationImplCopyWithImpl( + _$AppNotificationImpl _value, $Res Function(_$AppNotificationImpl) _then) + : super(_value, _then); + + /// Create a copy of AppNotification + /// with the given fields replaced by the non-null parameter values. + @pragma('vm:prefer-inline') + @override + $Res call({ + Object? id = null, + Object? sessionId = freezed, + Object? type = null, + Object? title = null, + Object? body = null, + Object? priority = null, + Object? data = freezed, + Object? timestamp = null, + Object? isRead = null, + }) { + return _then(_$AppNotificationImpl( + id: null == id + ? _value.id + : id // ignore: cast_nullable_to_non_nullable + as String, + sessionId: freezed == sessionId + ? _value.sessionId + : sessionId // ignore: cast_nullable_to_non_nullable + as String?, + type: null == type + ? _value.type + : type // ignore: cast_nullable_to_non_nullable + as NotificationType, + title: null == title + ? _value.title + : title // ignore: cast_nullable_to_non_nullable + as String, + body: null == body + ? _value.body + : body // ignore: cast_nullable_to_non_nullable + as String, + priority: null == priority + ? _value.priority + : priority // ignore: cast_nullable_to_non_nullable + as NotificationPriority, + data: freezed == data + ? _value._data + : data // ignore: cast_nullable_to_non_nullable + as Map?, + timestamp: null == timestamp + ? _value.timestamp + : timestamp // ignore: cast_nullable_to_non_nullable + as DateTime, + isRead: null == isRead + ? _value.isRead + : isRead // ignore: cast_nullable_to_non_nullable + as bool, + )); + } +} + +/// @nodoc +@JsonSerializable() +class _$AppNotificationImpl implements _AppNotification { + const _$AppNotificationImpl( + {required this.id, + this.sessionId, + required this.type, + required this.title, + required this.body, + this.priority = NotificationPriority.normal, + final Map? data, + required this.timestamp, + this.isRead = false}) + : _data = data; + + factory _$AppNotificationImpl.fromJson(Map json) => + _$$AppNotificationImplFromJson(json); + + @override + final String id; + @override + final String? sessionId; + @override + final NotificationType type; + @override + final String title; + @override + final String body; + @override + @JsonKey() + final NotificationPriority priority; + final Map? _data; + @override + Map? get data { + final value = _data; + if (value == null) return null; + if (_data is EqualUnmodifiableMapView) return _data; + // ignore: implicit_dynamic_type + return EqualUnmodifiableMapView(value); + } + + @override + final DateTime timestamp; + @override + @JsonKey() + final bool isRead; + + @override + String toString() { + return 'AppNotification(id: $id, sessionId: $sessionId, type: $type, title: $title, body: $body, priority: $priority, data: $data, timestamp: $timestamp, isRead: $isRead)'; + } + + @override + bool operator ==(Object other) { + return identical(this, other) || + (other.runtimeType == runtimeType && + other is _$AppNotificationImpl && + (identical(other.id, id) || other.id == id) && + (identical(other.sessionId, sessionId) || + other.sessionId == sessionId) && + (identical(other.type, type) || other.type == type) && + (identical(other.title, title) || other.title == title) && + (identical(other.body, body) || other.body == body) && + (identical(other.priority, priority) || + other.priority == priority) && + const DeepCollectionEquality().equals(other._data, _data) && + (identical(other.timestamp, timestamp) || + other.timestamp == timestamp) && + (identical(other.isRead, isRead) || other.isRead == isRead)); + } + + @JsonKey(includeFromJson: false, includeToJson: false) + @override + int get hashCode => Object.hash(runtimeType, id, sessionId, type, title, body, + priority, const DeepCollectionEquality().hash(_data), timestamp, isRead); + + /// Create a copy of AppNotification + /// with the given fields replaced by the non-null parameter values. + @JsonKey(includeFromJson: false, includeToJson: false) + @override + @pragma('vm:prefer-inline') + _$$AppNotificationImplCopyWith<_$AppNotificationImpl> get copyWith => + __$$AppNotificationImplCopyWithImpl<_$AppNotificationImpl>( + this, _$identity); + + @override + Map toJson() { + return _$$AppNotificationImplToJson( + this, + ); + } +} + +abstract class _AppNotification implements AppNotification { + const factory _AppNotification( + {required final String id, + final String? sessionId, + required final NotificationType type, + required final String title, + required final String body, + final NotificationPriority priority, + final Map? data, + required final DateTime timestamp, + final bool isRead}) = _$AppNotificationImpl; + + factory _AppNotification.fromJson(Map json) = + _$AppNotificationImpl.fromJson; + + @override + String get id; + @override + String? get sessionId; + @override + NotificationType get type; + @override + String get title; + @override + String get body; + @override + NotificationPriority get priority; + @override + Map? get data; + @override + DateTime get timestamp; + @override + bool get isRead; + + /// Create a copy of AppNotification + /// with the given fields replaced by the non-null parameter values. + @override + @JsonKey(includeFromJson: false, includeToJson: false) + _$$AppNotificationImplCopyWith<_$AppNotificationImpl> get copyWith => + throw _privateConstructorUsedError; +} diff --git a/apps/mobile/lib/core/models/notification_models.g.dart b/apps/mobile/lib/core/models/notification_models.g.dart new file mode 100644 index 0000000..c437e51 --- /dev/null +++ b/apps/mobile/lib/core/models/notification_models.g.dart @@ -0,0 +1,50 @@ +// GENERATED CODE - DO NOT MODIFY BY HAND + +part of 'notification_models.dart'; + +// ************************************************************************** +// JsonSerializableGenerator +// ************************************************************************** + +_$AppNotificationImpl _$$AppNotificationImplFromJson( + Map json) => + _$AppNotificationImpl( + id: json['id'] as String, + sessionId: json['sessionId'] as String?, + type: $enumDecode(_$NotificationTypeEnumMap, json['type']), + title: json['title'] as String, + body: json['body'] as String, + priority: $enumDecodeNullable( + _$NotificationPriorityEnumMap, json['priority']) ?? + NotificationPriority.normal, + data: json['data'] as Map?, + timestamp: DateTime.parse(json['timestamp'] as String), + isRead: json['isRead'] as bool? ?? false, + ); + +Map _$$AppNotificationImplToJson( + _$AppNotificationImpl instance) => + { + 'id': instance.id, + 'sessionId': instance.sessionId, + 'type': _$NotificationTypeEnumMap[instance.type]!, + 'title': instance.title, + 'body': instance.body, + 'priority': _$NotificationPriorityEnumMap[instance.priority]!, + 'data': instance.data, + 'timestamp': instance.timestamp.toIso8601String(), + 'isRead': instance.isRead, + }; + +const _$NotificationTypeEnumMap = { + NotificationType.approvalRequired: 'approvalRequired', + NotificationType.taskComplete: 'taskComplete', + NotificationType.error: 'error', + NotificationType.info: 'info', +}; + +const _$NotificationPriorityEnumMap = { + NotificationPriority.low: 'low', + NotificationPriority.normal: 'normal', + NotificationPriority.high: 'high', +}; diff --git a/apps/mobile/lib/core/models/session_models.dart b/apps/mobile/lib/core/models/session_models.dart new file mode 100644 index 0000000..bd1380b --- /dev/null +++ b/apps/mobile/lib/core/models/session_models.dart @@ -0,0 +1,52 @@ +import 'package:freezed_annotation/freezed_annotation.dart'; + +part 'session_models.freezed.dart'; +part 'session_models.g.dart'; + +enum SessionStatus { active, paused, closed } + +enum SessionEventType { + userMessage, + agentMessage, + toolUse, + toolResult, + sessionStart, + sessionEnd, + hookEvent, +} + +@freezed +class ChatSession with _$ChatSession { + const factory ChatSession({ + required String id, + required String agentType, + String? agentId, + @Default('') String title, + required String workingDirectory, + String? branch, + @Default(SessionStatus.active) SessionStatus status, + required DateTime createdAt, + DateTime? lastMessageAt, + DateTime? updatedAt, + @Default(true) bool synced, + }) = _ChatSession; + + factory ChatSession.fromJson(Map json) => + _$ChatSessionFromJson(json); +} + +@freezed +class SessionEvent with _$SessionEvent { + const factory SessionEvent({ + required String id, + required String sessionId, + required SessionEventType eventType, + required String title, + String? description, + required DateTime timestamp, + Map? metadata, + }) = _SessionEvent; + + factory SessionEvent.fromJson(Map json) => + _$SessionEventFromJson(json); +} diff --git a/apps/mobile/lib/core/models/session_models.freezed.dart b/apps/mobile/lib/core/models/session_models.freezed.dart new file mode 100644 index 0000000..f1165ee --- /dev/null +++ b/apps/mobile/lib/core/models/session_models.freezed.dart @@ -0,0 +1,674 @@ +// coverage:ignore-file +// GENERATED CODE - DO NOT MODIFY BY HAND +// ignore_for_file: type=lint +// ignore_for_file: unused_element, deprecated_member_use, deprecated_member_use_from_same_package, use_function_type_syntax_for_parameters, unnecessary_const, avoid_init_to_null, invalid_override_different_default_values_named, prefer_expression_function_bodies, annotate_overrides, invalid_annotation_target, unnecessary_question_mark + +part of 'session_models.dart'; + +// ************************************************************************** +// FreezedGenerator +// ************************************************************************** + +T _$identity(T value) => value; + +final _privateConstructorUsedError = UnsupportedError( + 'It seems like you constructed your class using `MyClass._()`. This constructor is only meant to be used by freezed and you are not supposed to need it nor use it.\nPlease check the documentation here for more information: https://github.com/rrousselGit/freezed#adding-getters-and-methods-to-our-models'); + +ChatSession _$ChatSessionFromJson(Map json) { + return _ChatSession.fromJson(json); +} + +/// @nodoc +mixin _$ChatSession { + String get id => throw _privateConstructorUsedError; + String get agentType => throw _privateConstructorUsedError; + String? get agentId => throw _privateConstructorUsedError; + String get title => throw _privateConstructorUsedError; + String get workingDirectory => throw _privateConstructorUsedError; + String? get branch => throw _privateConstructorUsedError; + SessionStatus get status => throw _privateConstructorUsedError; + DateTime get createdAt => throw _privateConstructorUsedError; + DateTime? get lastMessageAt => throw _privateConstructorUsedError; + DateTime? get updatedAt => throw _privateConstructorUsedError; + bool get synced => throw _privateConstructorUsedError; + + /// Serializes this ChatSession to a JSON map. + Map toJson() => throw _privateConstructorUsedError; + + /// Create a copy of ChatSession + /// with the given fields replaced by the non-null parameter values. + @JsonKey(includeFromJson: false, includeToJson: false) + $ChatSessionCopyWith get copyWith => + throw _privateConstructorUsedError; +} + +/// @nodoc +abstract class $ChatSessionCopyWith<$Res> { + factory $ChatSessionCopyWith( + ChatSession value, $Res Function(ChatSession) then) = + _$ChatSessionCopyWithImpl<$Res, ChatSession>; + @useResult + $Res call( + {String id, + String agentType, + String? agentId, + String title, + String workingDirectory, + String? branch, + SessionStatus status, + DateTime createdAt, + DateTime? lastMessageAt, + DateTime? updatedAt, + bool synced}); +} + +/// @nodoc +class _$ChatSessionCopyWithImpl<$Res, $Val extends ChatSession> + implements $ChatSessionCopyWith<$Res> { + _$ChatSessionCopyWithImpl(this._value, this._then); + + // ignore: unused_field + final $Val _value; + // ignore: unused_field + final $Res Function($Val) _then; + + /// Create a copy of ChatSession + /// with the given fields replaced by the non-null parameter values. + @pragma('vm:prefer-inline') + @override + $Res call({ + Object? id = null, + Object? agentType = null, + Object? agentId = freezed, + Object? title = null, + Object? workingDirectory = null, + Object? branch = freezed, + Object? status = null, + Object? createdAt = null, + Object? lastMessageAt = freezed, + Object? updatedAt = freezed, + Object? synced = null, + }) { + return _then(_value.copyWith( + id: null == id + ? _value.id + : id // ignore: cast_nullable_to_non_nullable + as String, + agentType: null == agentType + ? _value.agentType + : agentType // ignore: cast_nullable_to_non_nullable + as String, + agentId: freezed == agentId + ? _value.agentId + : agentId // ignore: cast_nullable_to_non_nullable + as String?, + title: null == title + ? _value.title + : title // ignore: cast_nullable_to_non_nullable + as String, + workingDirectory: null == workingDirectory + ? _value.workingDirectory + : workingDirectory // ignore: cast_nullable_to_non_nullable + as String, + branch: freezed == branch + ? _value.branch + : branch // ignore: cast_nullable_to_non_nullable + as String?, + status: null == status + ? _value.status + : status // ignore: cast_nullable_to_non_nullable + as SessionStatus, + createdAt: null == createdAt + ? _value.createdAt + : createdAt // ignore: cast_nullable_to_non_nullable + as DateTime, + lastMessageAt: freezed == lastMessageAt + ? _value.lastMessageAt + : lastMessageAt // ignore: cast_nullable_to_non_nullable + as DateTime?, + updatedAt: freezed == updatedAt + ? _value.updatedAt + : updatedAt // ignore: cast_nullable_to_non_nullable + as DateTime?, + synced: null == synced + ? _value.synced + : synced // ignore: cast_nullable_to_non_nullable + as bool, + ) as $Val); + } +} + +/// @nodoc +abstract class _$$ChatSessionImplCopyWith<$Res> + implements $ChatSessionCopyWith<$Res> { + factory _$$ChatSessionImplCopyWith( + _$ChatSessionImpl value, $Res Function(_$ChatSessionImpl) then) = + __$$ChatSessionImplCopyWithImpl<$Res>; + @override + @useResult + $Res call( + {String id, + String agentType, + String? agentId, + String title, + String workingDirectory, + String? branch, + SessionStatus status, + DateTime createdAt, + DateTime? lastMessageAt, + DateTime? updatedAt, + bool synced}); +} + +/// @nodoc +class __$$ChatSessionImplCopyWithImpl<$Res> + extends _$ChatSessionCopyWithImpl<$Res, _$ChatSessionImpl> + implements _$$ChatSessionImplCopyWith<$Res> { + __$$ChatSessionImplCopyWithImpl( + _$ChatSessionImpl _value, $Res Function(_$ChatSessionImpl) _then) + : super(_value, _then); + + /// Create a copy of ChatSession + /// with the given fields replaced by the non-null parameter values. + @pragma('vm:prefer-inline') + @override + $Res call({ + Object? id = null, + Object? agentType = null, + Object? agentId = freezed, + Object? title = null, + Object? workingDirectory = null, + Object? branch = freezed, + Object? status = null, + Object? createdAt = null, + Object? lastMessageAt = freezed, + Object? updatedAt = freezed, + Object? synced = null, + }) { + return _then(_$ChatSessionImpl( + id: null == id + ? _value.id + : id // ignore: cast_nullable_to_non_nullable + as String, + agentType: null == agentType + ? _value.agentType + : agentType // ignore: cast_nullable_to_non_nullable + as String, + agentId: freezed == agentId + ? _value.agentId + : agentId // ignore: cast_nullable_to_non_nullable + as String?, + title: null == title + ? _value.title + : title // ignore: cast_nullable_to_non_nullable + as String, + workingDirectory: null == workingDirectory + ? _value.workingDirectory + : workingDirectory // ignore: cast_nullable_to_non_nullable + as String, + branch: freezed == branch + ? _value.branch + : branch // ignore: cast_nullable_to_non_nullable + as String?, + status: null == status + ? _value.status + : status // ignore: cast_nullable_to_non_nullable + as SessionStatus, + createdAt: null == createdAt + ? _value.createdAt + : createdAt // ignore: cast_nullable_to_non_nullable + as DateTime, + lastMessageAt: freezed == lastMessageAt + ? _value.lastMessageAt + : lastMessageAt // ignore: cast_nullable_to_non_nullable + as DateTime?, + updatedAt: freezed == updatedAt + ? _value.updatedAt + : updatedAt // ignore: cast_nullable_to_non_nullable + as DateTime?, + synced: null == synced + ? _value.synced + : synced // ignore: cast_nullable_to_non_nullable + as bool, + )); + } +} + +/// @nodoc +@JsonSerializable() +class _$ChatSessionImpl implements _ChatSession { + const _$ChatSessionImpl( + {required this.id, + required this.agentType, + this.agentId, + this.title = '', + required this.workingDirectory, + this.branch, + this.status = SessionStatus.active, + required this.createdAt, + this.lastMessageAt, + this.updatedAt, + this.synced = true}); + + factory _$ChatSessionImpl.fromJson(Map json) => + _$$ChatSessionImplFromJson(json); + + @override + final String id; + @override + final String agentType; + @override + final String? agentId; + @override + @JsonKey() + final String title; + @override + final String workingDirectory; + @override + final String? branch; + @override + @JsonKey() + final SessionStatus status; + @override + final DateTime createdAt; + @override + final DateTime? lastMessageAt; + @override + final DateTime? updatedAt; + @override + @JsonKey() + final bool synced; + + @override + String toString() { + return 'ChatSession(id: $id, agentType: $agentType, agentId: $agentId, title: $title, workingDirectory: $workingDirectory, branch: $branch, status: $status, createdAt: $createdAt, lastMessageAt: $lastMessageAt, updatedAt: $updatedAt, synced: $synced)'; + } + + @override + bool operator ==(Object other) { + return identical(this, other) || + (other.runtimeType == runtimeType && + other is _$ChatSessionImpl && + (identical(other.id, id) || other.id == id) && + (identical(other.agentType, agentType) || + other.agentType == agentType) && + (identical(other.agentId, agentId) || other.agentId == agentId) && + (identical(other.title, title) || other.title == title) && + (identical(other.workingDirectory, workingDirectory) || + other.workingDirectory == workingDirectory) && + (identical(other.branch, branch) || other.branch == branch) && + (identical(other.status, status) || other.status == status) && + (identical(other.createdAt, createdAt) || + other.createdAt == createdAt) && + (identical(other.lastMessageAt, lastMessageAt) || + other.lastMessageAt == lastMessageAt) && + (identical(other.updatedAt, updatedAt) || + other.updatedAt == updatedAt) && + (identical(other.synced, synced) || other.synced == synced)); + } + + @JsonKey(includeFromJson: false, includeToJson: false) + @override + int get hashCode => Object.hash( + runtimeType, + id, + agentType, + agentId, + title, + workingDirectory, + branch, + status, + createdAt, + lastMessageAt, + updatedAt, + synced); + + /// Create a copy of ChatSession + /// with the given fields replaced by the non-null parameter values. + @JsonKey(includeFromJson: false, includeToJson: false) + @override + @pragma('vm:prefer-inline') + _$$ChatSessionImplCopyWith<_$ChatSessionImpl> get copyWith => + __$$ChatSessionImplCopyWithImpl<_$ChatSessionImpl>(this, _$identity); + + @override + Map toJson() { + return _$$ChatSessionImplToJson( + this, + ); + } +} + +abstract class _ChatSession implements ChatSession { + const factory _ChatSession( + {required final String id, + required final String agentType, + final String? agentId, + final String title, + required final String workingDirectory, + final String? branch, + final SessionStatus status, + required final DateTime createdAt, + final DateTime? lastMessageAt, + final DateTime? updatedAt, + final bool synced}) = _$ChatSessionImpl; + + factory _ChatSession.fromJson(Map json) = + _$ChatSessionImpl.fromJson; + + @override + String get id; + @override + String get agentType; + @override + String? get agentId; + @override + String get title; + @override + String get workingDirectory; + @override + String? get branch; + @override + SessionStatus get status; + @override + DateTime get createdAt; + @override + DateTime? get lastMessageAt; + @override + DateTime? get updatedAt; + @override + bool get synced; + + /// Create a copy of ChatSession + /// with the given fields replaced by the non-null parameter values. + @override + @JsonKey(includeFromJson: false, includeToJson: false) + _$$ChatSessionImplCopyWith<_$ChatSessionImpl> get copyWith => + throw _privateConstructorUsedError; +} + +SessionEvent _$SessionEventFromJson(Map json) { + return _SessionEvent.fromJson(json); +} + +/// @nodoc +mixin _$SessionEvent { + String get id => throw _privateConstructorUsedError; + String get sessionId => throw _privateConstructorUsedError; + SessionEventType get eventType => throw _privateConstructorUsedError; + String get title => throw _privateConstructorUsedError; + String? get description => throw _privateConstructorUsedError; + DateTime get timestamp => throw _privateConstructorUsedError; + Map? get metadata => throw _privateConstructorUsedError; + + /// Serializes this SessionEvent to a JSON map. + Map toJson() => throw _privateConstructorUsedError; + + /// Create a copy of SessionEvent + /// with the given fields replaced by the non-null parameter values. + @JsonKey(includeFromJson: false, includeToJson: false) + $SessionEventCopyWith get copyWith => + throw _privateConstructorUsedError; +} + +/// @nodoc +abstract class $SessionEventCopyWith<$Res> { + factory $SessionEventCopyWith( + SessionEvent value, $Res Function(SessionEvent) then) = + _$SessionEventCopyWithImpl<$Res, SessionEvent>; + @useResult + $Res call( + {String id, + String sessionId, + SessionEventType eventType, + String title, + String? description, + DateTime timestamp, + Map? metadata}); +} + +/// @nodoc +class _$SessionEventCopyWithImpl<$Res, $Val extends SessionEvent> + implements $SessionEventCopyWith<$Res> { + _$SessionEventCopyWithImpl(this._value, this._then); + + // ignore: unused_field + final $Val _value; + // ignore: unused_field + final $Res Function($Val) _then; + + /// Create a copy of SessionEvent + /// with the given fields replaced by the non-null parameter values. + @pragma('vm:prefer-inline') + @override + $Res call({ + Object? id = null, + Object? sessionId = null, + Object? eventType = null, + Object? title = null, + Object? description = freezed, + Object? timestamp = null, + Object? metadata = freezed, + }) { + return _then(_value.copyWith( + id: null == id + ? _value.id + : id // ignore: cast_nullable_to_non_nullable + as String, + sessionId: null == sessionId + ? _value.sessionId + : sessionId // ignore: cast_nullable_to_non_nullable + as String, + eventType: null == eventType + ? _value.eventType + : eventType // ignore: cast_nullable_to_non_nullable + as SessionEventType, + title: null == title + ? _value.title + : title // ignore: cast_nullable_to_non_nullable + as String, + description: freezed == description + ? _value.description + : description // ignore: cast_nullable_to_non_nullable + as String?, + timestamp: null == timestamp + ? _value.timestamp + : timestamp // ignore: cast_nullable_to_non_nullable + as DateTime, + metadata: freezed == metadata + ? _value.metadata + : metadata // ignore: cast_nullable_to_non_nullable + as Map?, + ) as $Val); + } +} + +/// @nodoc +abstract class _$$SessionEventImplCopyWith<$Res> + implements $SessionEventCopyWith<$Res> { + factory _$$SessionEventImplCopyWith( + _$SessionEventImpl value, $Res Function(_$SessionEventImpl) then) = + __$$SessionEventImplCopyWithImpl<$Res>; + @override + @useResult + $Res call( + {String id, + String sessionId, + SessionEventType eventType, + String title, + String? description, + DateTime timestamp, + Map? metadata}); +} + +/// @nodoc +class __$$SessionEventImplCopyWithImpl<$Res> + extends _$SessionEventCopyWithImpl<$Res, _$SessionEventImpl> + implements _$$SessionEventImplCopyWith<$Res> { + __$$SessionEventImplCopyWithImpl( + _$SessionEventImpl _value, $Res Function(_$SessionEventImpl) _then) + : super(_value, _then); + + /// Create a copy of SessionEvent + /// with the given fields replaced by the non-null parameter values. + @pragma('vm:prefer-inline') + @override + $Res call({ + Object? id = null, + Object? sessionId = null, + Object? eventType = null, + Object? title = null, + Object? description = freezed, + Object? timestamp = null, + Object? metadata = freezed, + }) { + return _then(_$SessionEventImpl( + id: null == id + ? _value.id + : id // ignore: cast_nullable_to_non_nullable + as String, + sessionId: null == sessionId + ? _value.sessionId + : sessionId // ignore: cast_nullable_to_non_nullable + as String, + eventType: null == eventType + ? _value.eventType + : eventType // ignore: cast_nullable_to_non_nullable + as SessionEventType, + title: null == title + ? _value.title + : title // ignore: cast_nullable_to_non_nullable + as String, + description: freezed == description + ? _value.description + : description // ignore: cast_nullable_to_non_nullable + as String?, + timestamp: null == timestamp + ? _value.timestamp + : timestamp // ignore: cast_nullable_to_non_nullable + as DateTime, + metadata: freezed == metadata + ? _value._metadata + : metadata // ignore: cast_nullable_to_non_nullable + as Map?, + )); + } +} + +/// @nodoc +@JsonSerializable() +class _$SessionEventImpl implements _SessionEvent { + const _$SessionEventImpl( + {required this.id, + required this.sessionId, + required this.eventType, + required this.title, + this.description, + required this.timestamp, + final Map? metadata}) + : _metadata = metadata; + + factory _$SessionEventImpl.fromJson(Map json) => + _$$SessionEventImplFromJson(json); + + @override + final String id; + @override + final String sessionId; + @override + final SessionEventType eventType; + @override + final String title; + @override + final String? description; + @override + final DateTime timestamp; + final Map? _metadata; + @override + Map? get metadata { + final value = _metadata; + if (value == null) return null; + if (_metadata is EqualUnmodifiableMapView) return _metadata; + // ignore: implicit_dynamic_type + return EqualUnmodifiableMapView(value); + } + + @override + String toString() { + return 'SessionEvent(id: $id, sessionId: $sessionId, eventType: $eventType, title: $title, description: $description, timestamp: $timestamp, metadata: $metadata)'; + } + + @override + bool operator ==(Object other) { + return identical(this, other) || + (other.runtimeType == runtimeType && + other is _$SessionEventImpl && + (identical(other.id, id) || other.id == id) && + (identical(other.sessionId, sessionId) || + other.sessionId == sessionId) && + (identical(other.eventType, eventType) || + other.eventType == eventType) && + (identical(other.title, title) || other.title == title) && + (identical(other.description, description) || + other.description == description) && + (identical(other.timestamp, timestamp) || + other.timestamp == timestamp) && + const DeepCollectionEquality().equals(other._metadata, _metadata)); + } + + @JsonKey(includeFromJson: false, includeToJson: false) + @override + int get hashCode => Object.hash(runtimeType, id, sessionId, eventType, title, + description, timestamp, const DeepCollectionEquality().hash(_metadata)); + + /// Create a copy of SessionEvent + /// with the given fields replaced by the non-null parameter values. + @JsonKey(includeFromJson: false, includeToJson: false) + @override + @pragma('vm:prefer-inline') + _$$SessionEventImplCopyWith<_$SessionEventImpl> get copyWith => + __$$SessionEventImplCopyWithImpl<_$SessionEventImpl>(this, _$identity); + + @override + Map toJson() { + return _$$SessionEventImplToJson( + this, + ); + } +} + +abstract class _SessionEvent implements SessionEvent { + const factory _SessionEvent( + {required final String id, + required final String sessionId, + required final SessionEventType eventType, + required final String title, + final String? description, + required final DateTime timestamp, + final Map? metadata}) = _$SessionEventImpl; + + factory _SessionEvent.fromJson(Map json) = + _$SessionEventImpl.fromJson; + + @override + String get id; + @override + String get sessionId; + @override + SessionEventType get eventType; + @override + String get title; + @override + String? get description; + @override + DateTime get timestamp; + @override + Map? get metadata; + + /// Create a copy of SessionEvent + /// with the given fields replaced by the non-null parameter values. + @override + @JsonKey(includeFromJson: false, includeToJson: false) + _$$SessionEventImplCopyWith<_$SessionEventImpl> get copyWith => + throw _privateConstructorUsedError; +} diff --git a/apps/mobile/lib/core/models/session_models.g.dart b/apps/mobile/lib/core/models/session_models.g.dart new file mode 100644 index 0000000..7e7ac7c --- /dev/null +++ b/apps/mobile/lib/core/models/session_models.g.dart @@ -0,0 +1,80 @@ +// GENERATED CODE - DO NOT MODIFY BY HAND + +part of 'session_models.dart'; + +// ************************************************************************** +// JsonSerializableGenerator +// ************************************************************************** + +_$ChatSessionImpl _$$ChatSessionImplFromJson(Map json) => + _$ChatSessionImpl( + id: json['id'] as String, + agentType: json['agentType'] as String, + agentId: json['agentId'] as String?, + title: json['title'] as String? ?? '', + workingDirectory: json['workingDirectory'] as String, + branch: json['branch'] as String?, + status: $enumDecodeNullable(_$SessionStatusEnumMap, json['status']) ?? + SessionStatus.active, + createdAt: DateTime.parse(json['createdAt'] as String), + lastMessageAt: json['lastMessageAt'] == null + ? null + : DateTime.parse(json['lastMessageAt'] as String), + updatedAt: json['updatedAt'] == null + ? null + : DateTime.parse(json['updatedAt'] as String), + synced: json['synced'] as bool? ?? true, + ); + +Map _$$ChatSessionImplToJson(_$ChatSessionImpl instance) => + { + 'id': instance.id, + 'agentType': instance.agentType, + 'agentId': instance.agentId, + 'title': instance.title, + 'workingDirectory': instance.workingDirectory, + 'branch': instance.branch, + 'status': _$SessionStatusEnumMap[instance.status]!, + 'createdAt': instance.createdAt.toIso8601String(), + 'lastMessageAt': instance.lastMessageAt?.toIso8601String(), + 'updatedAt': instance.updatedAt?.toIso8601String(), + 'synced': instance.synced, + }; + +const _$SessionStatusEnumMap = { + SessionStatus.active: 'active', + SessionStatus.paused: 'paused', + SessionStatus.closed: 'closed', +}; + +_$SessionEventImpl _$$SessionEventImplFromJson(Map json) => + _$SessionEventImpl( + id: json['id'] as String, + sessionId: json['sessionId'] as String, + eventType: $enumDecode(_$SessionEventTypeEnumMap, json['eventType']), + title: json['title'] as String, + description: json['description'] as String?, + timestamp: DateTime.parse(json['timestamp'] as String), + metadata: json['metadata'] as Map?, + ); + +Map _$$SessionEventImplToJson(_$SessionEventImpl instance) => + { + 'id': instance.id, + 'sessionId': instance.sessionId, + 'eventType': _$SessionEventTypeEnumMap[instance.eventType]!, + 'title': instance.title, + 'description': instance.description, + 'timestamp': instance.timestamp.toIso8601String(), + 'metadata': instance.metadata, + }; + +const _$SessionEventTypeEnumMap = { + SessionEventType.userMessage: 'userMessage', + SessionEventType.agentMessage: 'agentMessage', + SessionEventType.toolUse: 'toolUse', + SessionEventType.toolResult: 'toolResult', + SessionEventType.sessionStart: 'sessionStart', + SessionEventType.sessionEnd: 'sessionEnd', + SessionEventType.hookEvent: 'hookEvent', +}; diff --git a/apps/mobile/lib/core/monitoring/analytics_service.dart b/apps/mobile/lib/core/monitoring/analytics_service.dart new file mode 100644 index 0000000..a8302ce --- /dev/null +++ b/apps/mobile/lib/core/monitoring/analytics_service.dart @@ -0,0 +1,47 @@ +// Simple event analytics — no external SDK, logs locally and optionally to a self-hosted endpoint +// User must opt in (checked against AppPreferences) + +import 'package:flutter/foundation.dart'; + +class AnalyticsEvent { + final String name; + final Map properties; + final DateTime timestamp; + + const AnalyticsEvent({required this.name, this.properties = const {}, required this.timestamp}); + + Map toJson() => { + 'name': name, + 'properties': properties, + 'timestamp': timestamp.toIso8601String(), + }; +} + +class AnalyticsService { + static bool _enabled = false; + static final List _buffer = []; + static const int _maxBuffer = 100; + + static void setEnabled(bool enabled) { _enabled = enabled; } + static bool get isEnabled => _enabled; + + static void track(String event, {Map? properties}) { + if (!_enabled) return; + final e = AnalyticsEvent(name: event, properties: properties ?? {}, timestamp: DateTime.now()); + _buffer.add(e); + if (_buffer.length > _maxBuffer) _buffer.removeAt(0); + debugPrint('[Analytics] $event ${properties ?? {}}'); + } + + // Pre-defined events + static void trackSessionStarted(String agentType) => track('session_started', properties: {'agent_type': agentType}); + static void trackMessageSent() => track('message_sent'); + static void trackApprovalDecision(String decision) => track('approval_decision', properties: {'decision': decision}); + static void trackToolCardExpanded(String tool) => track('tool_card_expanded', properties: {'tool': tool}); + static void trackDiffViewed() => track('diff_viewed'); + static void trackVoiceInputUsed() => track('voice_input_used'); + static void trackAgentAdded(String type) => track('agent_added', properties: {'type': type}); + + static List get buffer => List.unmodifiable(_buffer); + static void clearBuffer() => _buffer.clear(); +} diff --git a/apps/mobile/lib/core/monitoring/sentry_service.dart b/apps/mobile/lib/core/monitoring/sentry_service.dart new file mode 100644 index 0000000..2ec1e18 --- /dev/null +++ b/apps/mobile/lib/core/monitoring/sentry_service.dart @@ -0,0 +1,56 @@ +import 'package:flutter/material.dart'; +import 'package:sentry_flutter/sentry_flutter.dart'; + +class SentryService { + static const String _dsn = String.fromEnvironment( + 'SENTRY_DSN', + defaultValue: '', + ); + + static bool get isConfigured => _dsn.isNotEmpty; + + // Initialize Sentry — call before runApp + static Future init(AppRunner appRunner) async { + if (!isConfigured) { + appRunner(); + return; + } + await SentryFlutter.init( + (options) { + options.dsn = _dsn; + options.environment = const String.fromEnvironment('APP_ENV', defaultValue: 'development'); + options.tracesSampleRate = 0.2; + options.profilesSampleRate = 0.1; + options.attachScreenshot = true; + options.enableAutoPerformanceTracing = true; + }, + appRunner: appRunner, + ); + } + + // Capture an exception manually + static Future captureException(Object exception, {StackTrace? stackTrace}) async { + if (!isConfigured) return; + await Sentry.captureException(exception, stackTrace: stackTrace); + } + + // Add breadcrumb + static void addBreadcrumb(String message, {String? category, Map? data}) { + if (!isConfigured) return; + Sentry.addBreadcrumb(Breadcrumb( + message: message, + category: category, + data: data, + )); + } + + // Set user context + static void setUser(String? id, String? username) { + if (!isConfigured) return; + Sentry.configureScope((scope) { + scope.setUser(id != null ? SentryUser(id: id, username: username) : null); + }); + } +} + +typedef AppRunner = void Function(); diff --git a/apps/mobile/lib/core/network/bridge_socket.dart b/apps/mobile/lib/core/network/bridge_socket.dart new file mode 100644 index 0000000..e9aa030 --- /dev/null +++ b/apps/mobile/lib/core/network/bridge_socket.dart @@ -0,0 +1,46 @@ +// Re-exports for backwards compatibility with generated code +export '../providers/websocket_provider.dart' + show webSocketServiceProvider, connectionStatusProvider, bridgeMessagesProvider; +export 'connection_state.dart' show ConnectionStatus; + +// Aliases +import 'dart:convert'; + +import 'package:flutter_riverpod/flutter_riverpod.dart'; +import 'websocket_messages.dart'; +import 'websocket_service.dart'; +import '../providers/websocket_provider.dart'; +import 'connection_state.dart'; + +/// Thin facade over [WebSocketService] that exposes a map-based API used by +/// feature providers generated before the typed-message redesign. +class BridgeSocket { + BridgeSocket(this._service); + + final WebSocketService _service; + + /// Stream of decoded JSON payloads from the bridge. + Stream> get messageStream => + _service.messages.map((msg) => msg.toJson()); + + /// Send a raw map as a JSON frame. + void send(Map data) { + _service.sendRaw(jsonEncode(data)); + } + + ConnectionStatus get currentStatus => _service.currentStatus; +} + +final _bridgeSocketProvider = Provider((ref) { + final service = ref.watch(webSocketServiceProvider); + return BridgeSocket(service); +}); + +/// Alias: bridgeSocketProvider exposes the [BridgeSocket] facade. +final bridgeSocketProvider = _bridgeSocketProvider; + +/// Alias: bridgeSocketStateProvider = connectionStatusProvider +final bridgeSocketStateProvider = connectionStatusProvider; + +/// Alias type: BridgeSocketState = ConnectionStatus +typedef BridgeSocketState = ConnectionStatus; diff --git a/apps/mobile/lib/core/network/connection_state.dart b/apps/mobile/lib/core/network/connection_state.dart new file mode 100644 index 0000000..ae2893a --- /dev/null +++ b/apps/mobile/lib/core/network/connection_state.dart @@ -0,0 +1,50 @@ +enum ConnectionStatus { + disconnected, + connecting, + connected, + reconnecting, + error, +} + +class ConnectionState { + final ConnectionStatus status; + final String? bridgeUrl; + final DateTime? lastConnectedAt; + final int reconnectAttempts; + final String? errorMessage; + + const ConnectionState({ + required this.status, + this.bridgeUrl, + this.lastConnectedAt, + this.reconnectAttempts = 0, + this.errorMessage, + }); + + const ConnectionState.initial() + : status = ConnectionStatus.disconnected, + bridgeUrl = null, + lastConnectedAt = null, + reconnectAttempts = 0, + errorMessage = null; + + ConnectionState copyWith({ + ConnectionStatus? status, + String? bridgeUrl, + DateTime? lastConnectedAt, + int? reconnectAttempts, + String? errorMessage, + }) { + return ConnectionState( + status: status ?? this.status, + bridgeUrl: bridgeUrl ?? this.bridgeUrl, + lastConnectedAt: lastConnectedAt ?? this.lastConnectedAt, + reconnectAttempts: reconnectAttempts ?? this.reconnectAttempts, + errorMessage: errorMessage ?? this.errorMessage, + ); + } + + @override + String toString() => + 'ConnectionState(status: $status, url: $bridgeUrl, attempts: $reconnectAttempts)'; +} diff --git a/apps/mobile/lib/core/network/websocket_messages.dart b/apps/mobile/lib/core/network/websocket_messages.dart new file mode 100644 index 0000000..860f750 --- /dev/null +++ b/apps/mobile/lib/core/network/websocket_messages.dart @@ -0,0 +1,341 @@ +import 'dart:convert'; +import 'package:uuid/uuid.dart'; + +enum BridgeMessageType { + // Connection + auth, + connectionAck, + connectionError, + heartbeatPing, + heartbeatPong, + // Sessions + sessionStart, + sessionReady, + sessionEnd, + // Chat + message, + streamStart, + streamChunk, + streamEnd, + // Tools + toolCall, + claudeEvent, + approvalRequired, + approvalResponse, + toolResult, + // Git + gitStatusRequest, + gitStatusResponse, + gitCommit, + gitDiff, + gitDiffResponse, + // Files + fileList, + fileListResponse, + fileRead, + fileReadResponse, + // Notifications + notification, + notificationAck, + // Errors + error, +} + +/// Converts a string message type (snake_case) to [BridgeMessageType]. +BridgeMessageType _typeFromString(String type) { + return switch (type) { + 'auth' => BridgeMessageType.auth, + 'connection_ack' => BridgeMessageType.connectionAck, + 'connection_error' => BridgeMessageType.connectionError, + 'heartbeat_ping' => BridgeMessageType.heartbeatPing, + 'heartbeat_pong' => BridgeMessageType.heartbeatPong, + 'session_start' => BridgeMessageType.sessionStart, + 'session_ready' => BridgeMessageType.sessionReady, + 'session_end' => BridgeMessageType.sessionEnd, + 'message' => BridgeMessageType.message, + 'stream_start' => BridgeMessageType.streamStart, + 'stream_chunk' => BridgeMessageType.streamChunk, + 'stream_end' => BridgeMessageType.streamEnd, + 'tool_call' => BridgeMessageType.toolCall, + 'claude_event' => BridgeMessageType.claudeEvent, + 'approval_required' => BridgeMessageType.approvalRequired, + 'approval_response' => BridgeMessageType.approvalResponse, + 'tool_result' => BridgeMessageType.toolResult, + 'git_status_request' => BridgeMessageType.gitStatusRequest, + 'git_status_response' => BridgeMessageType.gitStatusResponse, + 'git_commit' => BridgeMessageType.gitCommit, + 'git_diff' => BridgeMessageType.gitDiff, + 'git_diff_response' => BridgeMessageType.gitDiffResponse, + 'file_list' => BridgeMessageType.fileList, + 'file_list_response' => BridgeMessageType.fileListResponse, + 'file_read' => BridgeMessageType.fileRead, + 'file_read_response' => BridgeMessageType.fileReadResponse, + 'notification' => BridgeMessageType.notification, + 'notification_ack' => BridgeMessageType.notificationAck, + 'error' => BridgeMessageType.error, + _ => BridgeMessageType.error, + }; +} + +String _typeToString(BridgeMessageType type) { + return switch (type) { + BridgeMessageType.auth => 'auth', + BridgeMessageType.connectionAck => 'connection_ack', + BridgeMessageType.connectionError => 'connection_error', + BridgeMessageType.heartbeatPing => 'heartbeat_ping', + BridgeMessageType.heartbeatPong => 'heartbeat_pong', + BridgeMessageType.sessionStart => 'session_start', + BridgeMessageType.sessionReady => 'session_ready', + BridgeMessageType.sessionEnd => 'session_end', + BridgeMessageType.message => 'message', + BridgeMessageType.streamStart => 'stream_start', + BridgeMessageType.streamChunk => 'stream_chunk', + BridgeMessageType.streamEnd => 'stream_end', + BridgeMessageType.toolCall => 'tool_call', + BridgeMessageType.claudeEvent => 'claude_event', + BridgeMessageType.approvalRequired => 'approval_required', + BridgeMessageType.approvalResponse => 'approval_response', + BridgeMessageType.toolResult => 'tool_result', + BridgeMessageType.gitStatusRequest => 'git_status_request', + BridgeMessageType.gitStatusResponse => 'git_status_response', + BridgeMessageType.gitCommit => 'git_commit', + BridgeMessageType.gitDiff => 'git_diff', + BridgeMessageType.gitDiffResponse => 'git_diff_response', + BridgeMessageType.fileList => 'file_list', + BridgeMessageType.fileListResponse => 'file_list_response', + BridgeMessageType.fileRead => 'file_read', + BridgeMessageType.fileReadResponse => 'file_read_response', + BridgeMessageType.notification => 'notification', + BridgeMessageType.notificationAck => 'notification_ack', + BridgeMessageType.error => 'error', + }; +} + +const _uuid = Uuid(); + +class BridgeMessage { + final BridgeMessageType type; + final String? id; + final DateTime timestamp; + final Map payload; + + const BridgeMessage({ + required this.type, + this.id, + required this.timestamp, + required this.payload, + }); + + // --------------------------------------------------------------------------- + // Factories + // --------------------------------------------------------------------------- + + factory BridgeMessage.auth({ + required String token, + required String clientVersion, + required String platform, + }) { + return BridgeMessage( + type: BridgeMessageType.auth, + id: 'auth-${_uuid.v4()}', + timestamp: DateTime.now().toUtc(), + payload: { + 'token': token, + 'client_version': clientVersion, + 'platform': platform, + }, + ); + } + + factory BridgeMessage.heartbeatPing() { + return BridgeMessage( + type: BridgeMessageType.heartbeatPing, + timestamp: DateTime.now().toUtc(), + payload: {}, + ); + } + + factory BridgeMessage.sessionStart({ + required String agent, + String? sessionId, + required String workingDirectory, + bool resume = false, + }) { + return BridgeMessage( + type: BridgeMessageType.sessionStart, + id: 'req-${_uuid.v4()}', + timestamp: DateTime.now().toUtc(), + payload: { + 'agent': agent, + 'session_id': sessionId, + 'working_directory': workingDirectory, + 'resume': resume, + }, + ); + } + + factory BridgeMessage.message({ + required String sessionId, + required String content, + String role = 'user', + }) { + return BridgeMessage( + type: BridgeMessageType.message, + id: 'msg-${_uuid.v4()}', + timestamp: DateTime.now().toUtc(), + payload: { + 'session_id': sessionId, + 'content': content, + 'role': role, + }, + ); + } + + factory BridgeMessage.approvalResponse({ + required String sessionId, + required String toolCallId, + required String decision, + Map? modifications, + String? correlationId, + }) { + return BridgeMessage( + type: BridgeMessageType.approvalResponse, + id: correlationId ?? 'resp-${_uuid.v4()}', + timestamp: DateTime.now().toUtc(), + payload: { + 'session_id': sessionId, + 'tool_call_id': toolCallId, + 'decision': decision, + 'modifications': modifications, + }, + ); + } + + factory BridgeMessage.sessionEnd({ + required String sessionId, + String reason = 'user_request', + }) { + return BridgeMessage( + type: BridgeMessageType.sessionEnd, + timestamp: DateTime.now().toUtc(), + payload: { + 'session_id': sessionId, + 'reason': reason, + }, + ); + } + + factory BridgeMessage.gitStatusRequest({required String sessionId}) { + return BridgeMessage( + type: BridgeMessageType.gitStatusRequest, + id: 'git-${_uuid.v4()}', + timestamp: DateTime.now().toUtc(), + payload: {'session_id': sessionId}, + ); + } + + factory BridgeMessage.gitCommit({ + required String sessionId, + required String commitMessage, + List? files, + }) { + return BridgeMessage( + type: BridgeMessageType.gitCommit, + id: 'git-${_uuid.v4()}', + timestamp: DateTime.now().toUtc(), + payload: { + 'session_id': sessionId, + 'message': commitMessage, + 'files': files, + }, + ); + } + + factory BridgeMessage.gitDiff({ + required String sessionId, + List? files, + bool cached = false, + }) { + return BridgeMessage( + type: BridgeMessageType.gitDiff, + id: 'git-${_uuid.v4()}', + timestamp: DateTime.now().toUtc(), + payload: { + 'session_id': sessionId, + 'files': files, + 'cached': cached, + }, + ); + } + + factory BridgeMessage.fileList({ + required String sessionId, + required String path, + }) { + return BridgeMessage( + type: BridgeMessageType.fileList, + id: 'file-${_uuid.v4()}', + timestamp: DateTime.now().toUtc(), + payload: {'session_id': sessionId, 'path': path}, + ); + } + + factory BridgeMessage.fileRead({ + required String sessionId, + required String path, + int offset = 0, + int? limit, + }) { + return BridgeMessage( + type: BridgeMessageType.fileRead, + id: 'file-${_uuid.v4()}', + timestamp: DateTime.now().toUtc(), + payload: { + 'session_id': sessionId, + 'path': path, + 'offset': offset, + if (limit != null) 'limit': limit, + }, + ); + } + + factory BridgeMessage.notificationAck({ + required List notificationIds, + }) { + return BridgeMessage( + type: BridgeMessageType.notificationAck, + timestamp: DateTime.now().toUtc(), + payload: {'notification_ids': notificationIds}, + ); + } + + // --------------------------------------------------------------------------- + // Serialization + // --------------------------------------------------------------------------- + + factory BridgeMessage.fromJson(Map json) { + return BridgeMessage( + type: _typeFromString(json['type'] as String), + id: json['id'] as String?, + timestamp: json['timestamp'] != null + ? DateTime.parse(json['timestamp'] as String) + : DateTime.now().toUtc(), + payload: (json['payload'] as Map?) ?? {}, + ); + } + + Map toJson() { + final map = { + 'type': _typeToString(type), + 'timestamp': timestamp.toIso8601String(), + 'payload': payload, + }; + if (id != null) map['id'] = id; + return map; + } + + String toJsonString() => jsonEncode(toJson()); + + @override + String toString() => 'BridgeMessage(type: $type, id: $id)'; +} diff --git a/apps/mobile/lib/core/network/websocket_service.dart b/apps/mobile/lib/core/network/websocket_service.dart new file mode 100644 index 0000000..2939863 --- /dev/null +++ b/apps/mobile/lib/core/network/websocket_service.dart @@ -0,0 +1,222 @@ +import 'dart:async'; +import 'dart:convert'; + +import 'package:web_socket_channel/web_socket_channel.dart'; + +import 'connection_state.dart'; +import 'websocket_messages.dart'; + +/// WebSocket client service for communication with the ReCursor bridge server. +/// +/// Responsibilities: +/// - Connect / disconnect lifecycle +/// - Authentication handshake +/// - Heartbeat (ping every 15 s, expect pong within 10 s) +/// - Automatic reconnect with exponential back-off (1 → 2 → 4 → 8 … max 30 s) +/// - Serialize outgoing [BridgeMessage] to JSON +/// - Parse incoming JSON into [BridgeMessage] +class WebSocketService { + static const int _heartbeatIntervalSeconds = 15; + static const int _heartbeatTimeoutSeconds = 10; + static const int _maxReconnectDelaySeconds = 30; + + WebSocketChannel? _channel; + String? _url; + String? _token; + + final _messageController = StreamController.broadcast(); + final _statusController = StreamController.broadcast(); + + ConnectionStatus _status = ConnectionStatus.disconnected; + int _reconnectAttempts = 0; + bool _intentionalDisconnect = false; + + Timer? _heartbeatTimer; + Timer? _pongTimeoutTimer; + Timer? _reconnectTimer; + + // --------------------------------------------------------------------------- + // Public streams + // --------------------------------------------------------------------------- + + Stream get messages => _messageController.stream; + Stream get connectionStatus => _statusController.stream; + ConnectionStatus get currentStatus => _status; + + // --------------------------------------------------------------------------- + // Connect / Disconnect + // --------------------------------------------------------------------------- + + Future connect({required String url, required String token}) async { + _url = url; + _token = token; + _intentionalDisconnect = false; + _reconnectAttempts = 0; + await _doConnect(); + } + + Future _doConnect() async { + _setStatus(ConnectionStatus.connecting); + + try { + final uri = Uri.parse(_url!); + _channel = WebSocketChannel.connect(uri); + + // Wait for the channel to be ready (throws on auth/network failure). + await _channel!.ready; + + _setStatus(ConnectionStatus.connected); + _reconnectAttempts = 0; + + // Send auth immediately. + send(BridgeMessage.auth( + token: _token!, + clientVersion: '0.1.0', + platform: _platformString(), + )); + + // Start listening to incoming frames. + _channel!.stream.listen( + _onRawMessage, + onError: _onError, + onDone: _onDone, + cancelOnError: false, + ); + + _startHeartbeat(); + } catch (e) { + _setStatus(ConnectionStatus.error); + _scheduleReconnect(); + } + } + + void disconnect() { + _intentionalDisconnect = true; + _cleanUp(); + _setStatus(ConnectionStatus.disconnected); + } + + // --------------------------------------------------------------------------- + // Send + // --------------------------------------------------------------------------- + + void send(BridgeMessage message) { + if (_channel == null || _status != ConnectionStatus.connected) return; + _channel!.sink.add(message.toJsonString()); + } + + /// Send raw JSON string — primarily for testing. + void sendRaw(String json) { + _channel?.sink.add(json); + } + + // --------------------------------------------------------------------------- + // Internal helpers + // --------------------------------------------------------------------------- + + void _onRawMessage(dynamic data) { + try { + final json = jsonDecode(data as String) as Map; + final msg = BridgeMessage.fromJson(json); + + // Heartbeat pong — cancel timeout timer. + if (msg.type == BridgeMessageType.heartbeatPong) { + _pongTimeoutTimer?.cancel(); + _pongTimeoutTimer = null; + return; + } + + _messageController.add(msg); + } catch (_) { + // Malformed message — ignore. + } + } + + void _onError(Object error) { + _setStatus(ConnectionStatus.error); + _cleanUp(closeChannel: false); + if (!_intentionalDisconnect) _scheduleReconnect(); + } + + void _onDone() { + _setStatus(ConnectionStatus.disconnected); + _cleanUp(closeChannel: false); + if (!_intentionalDisconnect) _scheduleReconnect(); + } + + void _startHeartbeat() { + _heartbeatTimer?.cancel(); + _heartbeatTimer = Timer.periodic( + Duration(seconds: _heartbeatIntervalSeconds), + (_) => _sendPing(), + ); + } + + void _sendPing() { + if (_status != ConnectionStatus.connected) return; + send(BridgeMessage.heartbeatPing()); + + // Expect pong within timeout window. + _pongTimeoutTimer?.cancel(); + _pongTimeoutTimer = Timer( + Duration(seconds: _heartbeatTimeoutSeconds), + _onPongTimeout, + ); + } + + void _onPongTimeout() { + // No pong received — trigger reconnect. + _cleanUp(closeChannel: true); + _setStatus(ConnectionStatus.reconnecting); + if (!_intentionalDisconnect) _scheduleReconnect(); + } + + void _scheduleReconnect() { + if (_intentionalDisconnect) return; + _reconnectTimer?.cancel(); + + final delaySeconds = _exponentialDelay(_reconnectAttempts); + _reconnectAttempts++; + _setStatus(ConnectionStatus.reconnecting); + + _reconnectTimer = Timer(Duration(seconds: delaySeconds), () async { + if (!_intentionalDisconnect) await _doConnect(); + }); + } + + int _exponentialDelay(int attempt) { + final delay = (1 << attempt).clamp(1, _maxReconnectDelaySeconds); + return delay; + } + + void _cleanUp({bool closeChannel = true}) { + _heartbeatTimer?.cancel(); + _heartbeatTimer = null; + _pongTimeoutTimer?.cancel(); + _pongTimeoutTimer = null; + _reconnectTimer?.cancel(); + _reconnectTimer = null; + + if (closeChannel) { + _channel?.sink.close(); + _channel = null; + } + } + + void _setStatus(ConnectionStatus status) { + _status = status; + _statusController.add(status); + } + + String _platformString() { + // In a full implementation, use Platform.isIOS / Platform.isAndroid. + return 'flutter'; + } + + void dispose() { + _intentionalDisconnect = true; + _cleanUp(); + _messageController.close(); + _statusController.close(); + } +} diff --git a/apps/mobile/lib/core/notifications/notification_center.dart b/apps/mobile/lib/core/notifications/notification_center.dart new file mode 100644 index 0000000..992a0d9 --- /dev/null +++ b/apps/mobile/lib/core/notifications/notification_center.dart @@ -0,0 +1,48 @@ +import 'dart:async'; + +import '../models/notification_models.dart'; + +/// In-memory notification center. +/// Maintains the list of [AppNotification] items and broadcasts changes. +class NotificationCenter { + final _notifications = []; + final _controller = + StreamController>.broadcast(); + + Stream> get notifications => _controller.stream; + + List get currentNotifications => + List.unmodifiable(_notifications); + + int get unreadCount => + _notifications.where((n) => !n.isRead).length; + + void addNotification(AppNotification n) { + // Deduplicate by id. + _notifications.removeWhere((existing) => existing.id == n.id); + _notifications.insert(0, n); + _emit(); + } + + void markRead(String id) { + final index = _notifications.indexWhere((n) => n.id == id); + if (index == -1) return; + _notifications[index] = _notifications[index].copyWith(isRead: true); + _emit(); + } + + void markAllRead() { + for (var i = 0; i < _notifications.length; i++) { + _notifications[i] = _notifications[i].copyWith(isRead: true); + } + _emit(); + } + + void _emit() { + _controller.add(List.unmodifiable(_notifications)); + } + + void dispose() { + _controller.close(); + } +} diff --git a/apps/mobile/lib/core/notifications/notification_handler.dart b/apps/mobile/lib/core/notifications/notification_handler.dart new file mode 100644 index 0000000..534740a --- /dev/null +++ b/apps/mobile/lib/core/notifications/notification_handler.dart @@ -0,0 +1,94 @@ +import 'dart:async'; +import 'dart:ui'; + +import 'package:flutter/scheduler.dart'; + +import '../models/notification_models.dart'; +import '../network/websocket_messages.dart'; +import 'notification_center.dart'; +import 'notification_service.dart'; + +/// Routes incoming bridge [BridgeMessage] notifications. +/// - Foreground: adds to [NotificationCenter]. +/// - Background: calls [NotificationService.showNotification]. +class NotificationHandler { + NotificationHandler({ + required NotificationCenter center, + required NotificationService service, + }) : _center = center, + _service = service; + + final NotificationCenter _center; + final NotificationService _service; + + final _controller = + StreamController.broadcast(); + + Stream get notificationStream => _controller.stream; + + Future handle(BridgeMessage message) async { + if (message.type != BridgeMessageType.notification) return; + + final payload = message.payload; + final notification = _parseNotification(message.id, payload); + if (notification == null) return; + + _controller.add(notification); + + // Determine if the app is in the foreground. + final lifecycleState = SchedulerBinding.instance?.lifecycleState; + final isForeground = lifecycleState == AppLifecycleState.resumed; + + if (isForeground) { + _center.addNotification(notification); + } else { + _center.addNotification(notification); + await _service.showNotification(notification); + } + } + + AppNotification? _parseNotification( + String? id, Map payload) { + try { + final typeString = + payload['notification_type'] as String? ?? 'info'; + final type = _parseType(typeString); + final priorityString = payload['priority'] as String? ?? 'normal'; + final priority = _parsePriority(priorityString); + + return AppNotification( + id: id ?? payload['notification_id'] as String? ?? '', + sessionId: payload['session_id'] as String?, + type: type, + title: payload['title'] as String? ?? '', + body: payload['body'] as String? ?? '', + priority: priority, + data: payload['data'] as Map?, + timestamp: DateTime.now().toUtc(), + ); + } catch (_) { + return null; + } + } + + NotificationType _parseType(String value) { + return switch (value) { + 'approval_required' => NotificationType.approvalRequired, + 'task_complete' => NotificationType.taskComplete, + 'error' => NotificationType.error, + _ => NotificationType.info, + }; + } + + NotificationPriority _parsePriority(String value) { + return switch (value) { + 'low' => NotificationPriority.low, + 'high' => NotificationPriority.high, + _ => NotificationPriority.normal, + }; + } + + void dispose() { + _controller.close(); + } +} diff --git a/apps/mobile/lib/core/notifications/notification_service.dart b/apps/mobile/lib/core/notifications/notification_service.dart new file mode 100644 index 0000000..e823ad5 --- /dev/null +++ b/apps/mobile/lib/core/notifications/notification_service.dart @@ -0,0 +1,82 @@ +import 'package:flutter_local_notifications/flutter_local_notifications.dart'; + +import '../models/notification_models.dart'; + +/// Thin wrapper around [FlutterLocalNotificationsPlugin]. +/// Handles permission requests and displaying local notifications. +class NotificationService { + final _plugin = FlutterLocalNotificationsPlugin(); + + Future init() async { + const androidSettings = + AndroidInitializationSettings('@mipmap/ic_launcher'); + const iosSettings = DarwinInitializationSettings( + requestAlertPermission: true, + requestBadgePermission: true, + requestSoundPermission: true, + ); + const initSettings = InitializationSettings( + android: androidSettings, + iOS: iosSettings, + ); + + await _plugin.initialize(initSettings); + + // Request Android 13+ notification permission. + await _plugin + .resolvePlatformSpecificImplementation< + AndroidFlutterLocalNotificationsPlugin>() + ?.requestNotificationsPermission(); + } + + Future showNotification(AppNotification notification) async { + final androidDetails = AndroidNotificationDetails( + 'recursor_main', + 'ReCursor', + channelDescription: 'ReCursor agent notifications', + importance: _toAndroidImportance(notification.priority), + priority: _toAndroidPriority(notification.priority), + ); + const iosDetails = DarwinNotificationDetails(); + + final details = NotificationDetails( + android: androidDetails, + iOS: iosDetails, + ); + + // Use a stable integer derived from the UUID to identify the notification. + final id = notification.id.hashCode & 0x7FFFFFFF; + + await _plugin.show( + id, + notification.title, + notification.body, + details, + payload: notification.id, + ); + } + + Future cancelNotification(String id) async { + await _plugin.cancel(id.hashCode & 0x7FFFFFFF); + } + + Future cancelAll() async { + await _plugin.cancelAll(); + } + + Importance _toAndroidImportance(NotificationPriority priority) { + return switch (priority) { + NotificationPriority.low => Importance.low, + NotificationPriority.normal => Importance.defaultImportance, + NotificationPriority.high => Importance.high, + }; + } + + Priority _toAndroidPriority(NotificationPriority priority) { + return switch (priority) { + NotificationPriority.low => Priority.low, + NotificationPriority.normal => Priority.defaultPriority, + NotificationPriority.high => Priority.high, + }; + } +} diff --git a/apps/mobile/lib/core/providers/auth_provider.dart b/apps/mobile/lib/core/providers/auth_provider.dart new file mode 100644 index 0000000..6e50723 --- /dev/null +++ b/apps/mobile/lib/core/providers/auth_provider.dart @@ -0,0 +1,2 @@ +// Re-export auth providers from core/auth +export '../auth/auth_provider.dart'; diff --git a/apps/mobile/lib/core/providers/bridge_provider.dart b/apps/mobile/lib/core/providers/bridge_provider.dart new file mode 100644 index 0000000..c07d5e5 --- /dev/null +++ b/apps/mobile/lib/core/providers/bridge_provider.dart @@ -0,0 +1,40 @@ +import 'package:flutter_riverpod/flutter_riverpod.dart'; + +import '../network/connection_state.dart'; +import '../network/websocket_service.dart'; +import 'websocket_provider.dart'; + +/// Notifier that exposes connect/disconnect actions on the shared +/// [WebSocketService]. UI reads [bridgeProvider] for connection state and +/// calls `.notifier.connect(url, token)` to initiate a connection. +class BridgeNotifier extends Notifier { + @override + ConnectionStatus build() { + final service = ref.watch(webSocketServiceProvider); + // Sync initial status. + final initial = service.currentStatus; + + // Keep state in sync with the service stream. + final sub = service.connectionStatus.listen((s) { + state = s; + }); + ref.onDispose(sub.cancel); + + return initial; + } + + /// Connect to the bridge at [url] using [token]. + Future connect(String url, String token) { + final service = ref.read(webSocketServiceProvider); + return service.connect(url: url, token: token); + } + + /// Disconnect from the bridge. + void disconnect() { + final service = ref.read(webSocketServiceProvider); + service.disconnect(); + } +} + +final bridgeProvider = + NotifierProvider(BridgeNotifier.new); diff --git a/apps/mobile/lib/core/providers/database_provider.dart b/apps/mobile/lib/core/providers/database_provider.dart new file mode 100644 index 0000000..597a6bc --- /dev/null +++ b/apps/mobile/lib/core/providers/database_provider.dart @@ -0,0 +1,9 @@ +import 'package:flutter_riverpod/flutter_riverpod.dart'; + +import '../storage/database.dart'; + +final databaseProvider = Provider((ref) { + final db = AppDatabase(); + ref.onDispose(db.close); + return db; +}); diff --git a/apps/mobile/lib/core/providers/notification_provider.dart b/apps/mobile/lib/core/providers/notification_provider.dart new file mode 100644 index 0000000..81e4bbd --- /dev/null +++ b/apps/mobile/lib/core/providers/notification_provider.dart @@ -0,0 +1,18 @@ +import 'package:flutter_riverpod/flutter_riverpod.dart'; + +import '../models/notification_models.dart'; +import '../notifications/notification_center.dart'; + +final notificationCenterProvider = Provider((ref) { + final center = NotificationCenter(); + ref.onDispose(center.dispose); + return center; +}); + +final notificationsProvider = StreamProvider>((ref) { + return ref.watch(notificationCenterProvider).notifications; +}); + +final unreadCountProvider = Provider((ref) { + return ref.watch(notificationCenterProvider).unreadCount; +}); diff --git a/apps/mobile/lib/core/providers/preferences_provider.dart b/apps/mobile/lib/core/providers/preferences_provider.dart new file mode 100644 index 0000000..2738690 --- /dev/null +++ b/apps/mobile/lib/core/providers/preferences_provider.dart @@ -0,0 +1,3 @@ +// appPreferencesProvider is declared in theme_provider.dart and overridden +// in main.dart with an initialized AppPreferences instance. +export 'theme_provider.dart' show appPreferencesProvider; diff --git a/apps/mobile/lib/core/providers/theme_provider.dart b/apps/mobile/lib/core/providers/theme_provider.dart new file mode 100644 index 0000000..4d0e9e7 --- /dev/null +++ b/apps/mobile/lib/core/providers/theme_provider.dart @@ -0,0 +1,53 @@ +import 'package:flutter/material.dart'; +import 'package:flutter_riverpod/flutter_riverpod.dart'; + +import '../storage/preferences.dart'; + +// --------------------------------------------------------------------------- +// Preferences provider — must be overridden in ProviderScope with a real +// AppPreferences instance that has already called init(). +// --------------------------------------------------------------------------- + +final appPreferencesProvider = Provider((ref) { + throw UnimplementedError('appPreferencesProvider must be overridden in ProviderScope'); +}); + +// --------------------------------------------------------------------------- +// themeModeProvider — persists to AppPreferences when mutated +// --------------------------------------------------------------------------- + +final themeModeProvider = StateNotifierProvider<_ThemeModeNotifier, ThemeMode>((ref) { + final prefs = ref.watch(appPreferencesProvider); + return _ThemeModeNotifier(prefs); +}); + +class _ThemeModeNotifier extends StateNotifier { + final AppPreferences _prefs; + + _ThemeModeNotifier(this._prefs) : super(_prefs.getThemeMode()); + + Future setThemeMode(ThemeMode mode) async { + state = mode; + await _prefs.setThemeMode(mode); + } +} + +// --------------------------------------------------------------------------- +// highContrastProvider — persists to AppPreferences when mutated +// --------------------------------------------------------------------------- + +final highContrastProvider = StateNotifierProvider<_HighContrastNotifier, bool>((ref) { + final prefs = ref.watch(appPreferencesProvider); + return _HighContrastNotifier(prefs); +}); + +class _HighContrastNotifier extends StateNotifier { + final AppPreferences _prefs; + + _HighContrastNotifier(this._prefs) : super(_prefs.getHighContrast()); + + Future setHighContrast(bool val) async { + state = val; + await _prefs.setHighContrast(val); + } +} diff --git a/apps/mobile/lib/core/providers/websocket_provider.dart b/apps/mobile/lib/core/providers/websocket_provider.dart new file mode 100644 index 0000000..0034b3c --- /dev/null +++ b/apps/mobile/lib/core/providers/websocket_provider.dart @@ -0,0 +1,21 @@ +import 'package:flutter_riverpod/flutter_riverpod.dart'; + +import '../network/connection_state.dart'; +import '../network/websocket_messages.dart'; +import '../network/websocket_service.dart'; + +final webSocketServiceProvider = Provider((ref) { + final service = WebSocketService(); + ref.onDispose(service.dispose); + return service; +}); + +final connectionStatusProvider = StreamProvider((ref) { + final service = ref.watch(webSocketServiceProvider); + return service.connectionStatus; +}); + +final bridgeMessagesProvider = StreamProvider((ref) { + final service = ref.watch(webSocketServiceProvider); + return service.messages; +}); diff --git a/apps/mobile/lib/core/storage/daos/message_dao.dart b/apps/mobile/lib/core/storage/daos/message_dao.dart new file mode 100644 index 0000000..195f388 --- /dev/null +++ b/apps/mobile/lib/core/storage/daos/message_dao.dart @@ -0,0 +1,45 @@ +import 'package:drift/drift.dart'; + +import '../database.dart'; +import '../tables/messages_table.dart'; + +part 'message_dao.g.dart'; + +@DriftAccessor(tables: [Messages]) +class MessageDao extends DatabaseAccessor + with _$MessageDaoMixin { + MessageDao(super.db); + + /// Watch all messages for a session, ordered by creation time ascending. + Stream> watchMessagesForSession(String sessionId) { + return (select(messages) + ..where((m) => m.sessionId.equals(sessionId)) + ..orderBy([(m) => OrderingTerm.asc(m.createdAt)])) + .watch(); + } + + /// Fetch all messages for a session (one-shot). + Future> getMessagesForSession(String sessionId) { + return (select(messages) + ..where((m) => m.sessionId.equals(sessionId)) + ..orderBy([(m) => OrderingTerm.asc(m.createdAt)])) + .get(); + } + + /// Insert a new message row. + Future insertMessage(MessagesCompanion message) async { + await into(messages).insert(message); + } + + /// Update an existing message row. + Future updateMessage(MessagesCompanion message) async { + await into(messages).insertOnConflictUpdate(message); + } + + /// Delete all messages belonging to [sessionId]. + Future deleteMessagesForSession(String sessionId) async { + await (delete(messages) + ..where((m) => m.sessionId.equals(sessionId))) + .go(); + } +} diff --git a/apps/mobile/lib/core/storage/daos/message_dao.g.dart b/apps/mobile/lib/core/storage/daos/message_dao.g.dart new file mode 100644 index 0000000..dcbfe5d --- /dev/null +++ b/apps/mobile/lib/core/storage/daos/message_dao.g.dart @@ -0,0 +1,9 @@ +// GENERATED CODE - DO NOT MODIFY BY HAND + +part of 'message_dao.dart'; + +// ignore_for_file: type=lint +mixin _$MessageDaoMixin on DatabaseAccessor { + $SessionsTable get sessions => attachedDatabase.sessions; + $MessagesTable get messages => attachedDatabase.messages; +} diff --git a/apps/mobile/lib/core/storage/daos/session_dao.dart b/apps/mobile/lib/core/storage/daos/session_dao.dart new file mode 100644 index 0000000..412aeca --- /dev/null +++ b/apps/mobile/lib/core/storage/daos/session_dao.dart @@ -0,0 +1,43 @@ +import 'package:drift/drift.dart'; + +import '../database.dart'; +import '../tables/sessions_table.dart'; + +part 'session_dao.g.dart'; + +@DriftAccessor(tables: [Sessions]) +class SessionDao extends DatabaseAccessor + with _$SessionDaoMixin { + SessionDao(super.db); + + /// Watch all sessions ordered by most recently updated. + Stream> watchAllSessions() { + return (select(sessions) + ..orderBy([(s) => OrderingTerm.desc(s.updatedAt)])) + .watch(); + } + + /// Fetch a single session by ID. + Future getSession(String id) { + return (select(sessions)..where((s) => s.id.equals(id))) + .getSingleOrNull(); + } + + /// Insert or update a session row. + Future upsertSession(SessionsCompanion session) async { + await into(sessions).insertOnConflictUpdate(session); + } + + /// Delete a session by ID. + Future deleteSession(String id) async { + await (delete(sessions)..where((s) => s.id.equals(id))).go(); + } + + /// Return the count of active sessions. + Future getActiveSessionCount() async { + final query = select(sessions) + ..where((s) => s.status.equals('active')); + final rows = await query.get(); + return rows.length; + } +} diff --git a/apps/mobile/lib/core/storage/daos/session_dao.g.dart b/apps/mobile/lib/core/storage/daos/session_dao.g.dart new file mode 100644 index 0000000..635e721 --- /dev/null +++ b/apps/mobile/lib/core/storage/daos/session_dao.g.dart @@ -0,0 +1,8 @@ +// GENERATED CODE - DO NOT MODIFY BY HAND + +part of 'session_dao.dart'; + +// ignore_for_file: type=lint +mixin _$SessionDaoMixin on DatabaseAccessor { + $SessionsTable get sessions => attachedDatabase.sessions; +} diff --git a/apps/mobile/lib/core/storage/daos/sync_dao.dart b/apps/mobile/lib/core/storage/daos/sync_dao.dart new file mode 100644 index 0000000..41e7cc8 --- /dev/null +++ b/apps/mobile/lib/core/storage/daos/sync_dao.dart @@ -0,0 +1,50 @@ +import 'package:drift/drift.dart'; + +import '../database.dart'; +import '../tables/sync_queue_table.dart'; + +part 'sync_dao.g.dart'; + +@DriftAccessor(tables: [SyncQueue]) +class SyncDao extends DatabaseAccessor with _$SyncDaoMixin { + SyncDao(super.db); + + /// Return all items that have not yet been successfully synced. + Future> getPendingItems() { + return (select(syncQueue) + ..where((q) => q.synced.equals(false)) + ..orderBy([(q) => OrderingTerm.asc(q.createdAt)])) + .get(); + } + + /// Add a new item to the sync queue. + Future enqueue(SyncQueueCompanion item) async { + await into(syncQueue).insert(item); + } + + /// Mark an item as successfully synced. + Future markSynced(int id) async { + await (update(syncQueue)..where((q) => q.id.equals(id))).write( + const SyncQueueCompanion(synced: Value(true)), + ); + } + + /// Increment retry count and record the last error for an item. + Future incrementRetry(int id, String error) async { + final item = await (select(syncQueue)..where((q) => q.id.equals(id))) + .getSingleOrNull(); + if (item == null) return; + + await (update(syncQueue)..where((q) => q.id.equals(id))).write( + SyncQueueCompanion( + retryCount: Value(item.retryCount + 1), + lastError: Value(error), + ), + ); + } + + /// Remove all items that have been successfully synced. + Future clearSynced() async { + await (delete(syncQueue)..where((q) => q.synced.equals(true))).go(); + } +} diff --git a/apps/mobile/lib/core/storage/daos/sync_dao.g.dart b/apps/mobile/lib/core/storage/daos/sync_dao.g.dart new file mode 100644 index 0000000..821bb34 --- /dev/null +++ b/apps/mobile/lib/core/storage/daos/sync_dao.g.dart @@ -0,0 +1,8 @@ +// GENERATED CODE - DO NOT MODIFY BY HAND + +part of 'sync_dao.dart'; + +// ignore_for_file: type=lint +mixin _$SyncDaoMixin on DatabaseAccessor { + $SyncQueueTable get syncQueue => attachedDatabase.syncQueue; +} diff --git a/apps/mobile/lib/core/storage/database.dart b/apps/mobile/lib/core/storage/database.dart new file mode 100644 index 0000000..4367fd0 --- /dev/null +++ b/apps/mobile/lib/core/storage/database.dart @@ -0,0 +1,40 @@ +import 'package:drift/drift.dart'; +import 'package:drift_flutter/drift_flutter.dart'; + +import 'daos/message_dao.dart'; +import 'daos/session_dao.dart'; +import 'daos/sync_dao.dart'; +import 'tables/agents_table.dart'; +import 'tables/approvals_table.dart'; +import 'tables/messages_table.dart'; +import 'tables/sessions_table.dart'; +import 'tables/sync_queue_table.dart'; + +part 'database.g.dart'; + +@DriftDatabase( + tables: [ + Sessions, + Messages, + Agents, + Approvals, + SyncQueue, + ], + daos: [ + SessionDao, + MessageDao, + SyncDao, + ], +) +class AppDatabase extends _$AppDatabase { + AppDatabase() : super(_openConnection()); + + @override + int get schemaVersion => 1; +} + +LazyDatabase _openConnection() { + return LazyDatabase(() async { + return driftDatabase(name: 'recursor_app'); + }); +} diff --git a/apps/mobile/lib/core/storage/database.g.dart b/apps/mobile/lib/core/storage/database.g.dart new file mode 100644 index 0000000..a281ad4 --- /dev/null +++ b/apps/mobile/lib/core/storage/database.g.dart @@ -0,0 +1,4291 @@ +// GENERATED CODE - DO NOT MODIFY BY HAND + +part of 'database.dart'; + +// ignore_for_file: type=lint +class $SessionsTable extends Sessions with TableInfo<$SessionsTable, Session> { + @override + final GeneratedDatabase attachedDatabase; + final String? _alias; + $SessionsTable(this.attachedDatabase, [this._alias]); + static const VerificationMeta _idMeta = const VerificationMeta('id'); + @override + late final GeneratedColumn id = GeneratedColumn( + 'id', aliasedName, false, + type: DriftSqlType.string, requiredDuringInsert: true); + static const VerificationMeta _agentTypeMeta = + const VerificationMeta('agentType'); + @override + late final GeneratedColumn agentType = GeneratedColumn( + 'agent_type', aliasedName, false, + type: DriftSqlType.string, requiredDuringInsert: true); + static const VerificationMeta _agentIdMeta = + const VerificationMeta('agentId'); + @override + late final GeneratedColumn agentId = GeneratedColumn( + 'agent_id', aliasedName, true, + type: DriftSqlType.string, requiredDuringInsert: false); + static const VerificationMeta _titleMeta = const VerificationMeta('title'); + @override + late final GeneratedColumn title = GeneratedColumn( + 'title', aliasedName, false, + type: DriftSqlType.string, + requiredDuringInsert: false, + defaultValue: const Constant('')); + static const VerificationMeta _workingDirectoryMeta = + const VerificationMeta('workingDirectory'); + @override + late final GeneratedColumn workingDirectory = GeneratedColumn( + 'working_directory', aliasedName, false, + type: DriftSqlType.string, requiredDuringInsert: true); + static const VerificationMeta _branchMeta = const VerificationMeta('branch'); + @override + late final GeneratedColumn branch = GeneratedColumn( + 'branch', aliasedName, true, + type: DriftSqlType.string, requiredDuringInsert: false); + static const VerificationMeta _statusMeta = const VerificationMeta('status'); + @override + late final GeneratedColumn status = GeneratedColumn( + 'status', aliasedName, false, + type: DriftSqlType.string, requiredDuringInsert: true); + static const VerificationMeta _createdAtMeta = + const VerificationMeta('createdAt'); + @override + late final GeneratedColumn createdAt = GeneratedColumn( + 'created_at', aliasedName, false, + type: DriftSqlType.dateTime, requiredDuringInsert: true); + static const VerificationMeta _lastMessageAtMeta = + const VerificationMeta('lastMessageAt'); + @override + late final GeneratedColumn lastMessageAt = + GeneratedColumn('last_message_at', aliasedName, true, + type: DriftSqlType.dateTime, requiredDuringInsert: false); + static const VerificationMeta _updatedAtMeta = + const VerificationMeta('updatedAt'); + @override + late final GeneratedColumn updatedAt = GeneratedColumn( + 'updated_at', aliasedName, false, + type: DriftSqlType.dateTime, requiredDuringInsert: true); + static const VerificationMeta _syncedMeta = const VerificationMeta('synced'); + @override + late final GeneratedColumn synced = GeneratedColumn( + 'synced', aliasedName, false, + type: DriftSqlType.bool, + requiredDuringInsert: false, + defaultConstraints: + GeneratedColumn.constraintIsAlways('CHECK ("synced" IN (0, 1))'), + defaultValue: const Constant(true)); + @override + List get $columns => [ + id, + agentType, + agentId, + title, + workingDirectory, + branch, + status, + createdAt, + lastMessageAt, + updatedAt, + synced + ]; + @override + String get aliasedName => _alias ?? actualTableName; + @override + String get actualTableName => $name; + static const String $name = 'sessions'; + @override + VerificationContext validateIntegrity(Insertable instance, + {bool isInserting = false}) { + final context = VerificationContext(); + final data = instance.toColumns(true); + if (data.containsKey('id')) { + context.handle(_idMeta, id.isAcceptableOrUnknown(data['id']!, _idMeta)); + } else if (isInserting) { + context.missing(_idMeta); + } + if (data.containsKey('agent_type')) { + context.handle(_agentTypeMeta, + agentType.isAcceptableOrUnknown(data['agent_type']!, _agentTypeMeta)); + } else if (isInserting) { + context.missing(_agentTypeMeta); + } + if (data.containsKey('agent_id')) { + context.handle(_agentIdMeta, + agentId.isAcceptableOrUnknown(data['agent_id']!, _agentIdMeta)); + } + if (data.containsKey('title')) { + context.handle( + _titleMeta, title.isAcceptableOrUnknown(data['title']!, _titleMeta)); + } + if (data.containsKey('working_directory')) { + context.handle( + _workingDirectoryMeta, + workingDirectory.isAcceptableOrUnknown( + data['working_directory']!, _workingDirectoryMeta)); + } else if (isInserting) { + context.missing(_workingDirectoryMeta); + } + if (data.containsKey('branch')) { + context.handle(_branchMeta, + branch.isAcceptableOrUnknown(data['branch']!, _branchMeta)); + } + if (data.containsKey('status')) { + context.handle(_statusMeta, + status.isAcceptableOrUnknown(data['status']!, _statusMeta)); + } else if (isInserting) { + context.missing(_statusMeta); + } + if (data.containsKey('created_at')) { + context.handle(_createdAtMeta, + createdAt.isAcceptableOrUnknown(data['created_at']!, _createdAtMeta)); + } else if (isInserting) { + context.missing(_createdAtMeta); + } + if (data.containsKey('last_message_at')) { + context.handle( + _lastMessageAtMeta, + lastMessageAt.isAcceptableOrUnknown( + data['last_message_at']!, _lastMessageAtMeta)); + } + if (data.containsKey('updated_at')) { + context.handle(_updatedAtMeta, + updatedAt.isAcceptableOrUnknown(data['updated_at']!, _updatedAtMeta)); + } else if (isInserting) { + context.missing(_updatedAtMeta); + } + if (data.containsKey('synced')) { + context.handle(_syncedMeta, + synced.isAcceptableOrUnknown(data['synced']!, _syncedMeta)); + } + return context; + } + + @override + Set get $primaryKey => {id}; + @override + Session map(Map data, {String? tablePrefix}) { + final effectivePrefix = tablePrefix != null ? '$tablePrefix.' : ''; + return Session( + id: attachedDatabase.typeMapping + .read(DriftSqlType.string, data['${effectivePrefix}id'])!, + agentType: attachedDatabase.typeMapping + .read(DriftSqlType.string, data['${effectivePrefix}agent_type'])!, + agentId: attachedDatabase.typeMapping + .read(DriftSqlType.string, data['${effectivePrefix}agent_id']), + title: attachedDatabase.typeMapping + .read(DriftSqlType.string, data['${effectivePrefix}title'])!, + workingDirectory: attachedDatabase.typeMapping.read( + DriftSqlType.string, data['${effectivePrefix}working_directory'])!, + branch: attachedDatabase.typeMapping + .read(DriftSqlType.string, data['${effectivePrefix}branch']), + status: attachedDatabase.typeMapping + .read(DriftSqlType.string, data['${effectivePrefix}status'])!, + createdAt: attachedDatabase.typeMapping + .read(DriftSqlType.dateTime, data['${effectivePrefix}created_at'])!, + lastMessageAt: attachedDatabase.typeMapping.read( + DriftSqlType.dateTime, data['${effectivePrefix}last_message_at']), + updatedAt: attachedDatabase.typeMapping + .read(DriftSqlType.dateTime, data['${effectivePrefix}updated_at'])!, + synced: attachedDatabase.typeMapping + .read(DriftSqlType.bool, data['${effectivePrefix}synced'])!, + ); + } + + @override + $SessionsTable createAlias(String alias) { + return $SessionsTable(attachedDatabase, alias); + } +} + +class Session extends DataClass implements Insertable { + final String id; + final String agentType; + final String? agentId; + final String title; + final String workingDirectory; + final String? branch; + + /// "active" | "paused" | "closed" + final String status; + final DateTime createdAt; + final DateTime? lastMessageAt; + final DateTime updatedAt; + final bool synced; + const Session( + {required this.id, + required this.agentType, + this.agentId, + required this.title, + required this.workingDirectory, + this.branch, + required this.status, + required this.createdAt, + this.lastMessageAt, + required this.updatedAt, + required this.synced}); + @override + Map toColumns(bool nullToAbsent) { + final map = {}; + map['id'] = Variable(id); + map['agent_type'] = Variable(agentType); + if (!nullToAbsent || agentId != null) { + map['agent_id'] = Variable(agentId); + } + map['title'] = Variable(title); + map['working_directory'] = Variable(workingDirectory); + if (!nullToAbsent || branch != null) { + map['branch'] = Variable(branch); + } + map['status'] = Variable(status); + map['created_at'] = Variable(createdAt); + if (!nullToAbsent || lastMessageAt != null) { + map['last_message_at'] = Variable(lastMessageAt); + } + map['updated_at'] = Variable(updatedAt); + map['synced'] = Variable(synced); + return map; + } + + SessionsCompanion toCompanion(bool nullToAbsent) { + return SessionsCompanion( + id: Value(id), + agentType: Value(agentType), + agentId: agentId == null && nullToAbsent + ? const Value.absent() + : Value(agentId), + title: Value(title), + workingDirectory: Value(workingDirectory), + branch: + branch == null && nullToAbsent ? const Value.absent() : Value(branch), + status: Value(status), + createdAt: Value(createdAt), + lastMessageAt: lastMessageAt == null && nullToAbsent + ? const Value.absent() + : Value(lastMessageAt), + updatedAt: Value(updatedAt), + synced: Value(synced), + ); + } + + factory Session.fromJson(Map json, + {ValueSerializer? serializer}) { + serializer ??= driftRuntimeOptions.defaultSerializer; + return Session( + id: serializer.fromJson(json['id']), + agentType: serializer.fromJson(json['agentType']), + agentId: serializer.fromJson(json['agentId']), + title: serializer.fromJson(json['title']), + workingDirectory: serializer.fromJson(json['workingDirectory']), + branch: serializer.fromJson(json['branch']), + status: serializer.fromJson(json['status']), + createdAt: serializer.fromJson(json['createdAt']), + lastMessageAt: serializer.fromJson(json['lastMessageAt']), + updatedAt: serializer.fromJson(json['updatedAt']), + synced: serializer.fromJson(json['synced']), + ); + } + @override + Map toJson({ValueSerializer? serializer}) { + serializer ??= driftRuntimeOptions.defaultSerializer; + return { + 'id': serializer.toJson(id), + 'agentType': serializer.toJson(agentType), + 'agentId': serializer.toJson(agentId), + 'title': serializer.toJson(title), + 'workingDirectory': serializer.toJson(workingDirectory), + 'branch': serializer.toJson(branch), + 'status': serializer.toJson(status), + 'createdAt': serializer.toJson(createdAt), + 'lastMessageAt': serializer.toJson(lastMessageAt), + 'updatedAt': serializer.toJson(updatedAt), + 'synced': serializer.toJson(synced), + }; + } + + Session copyWith( + {String? id, + String? agentType, + Value agentId = const Value.absent(), + String? title, + String? workingDirectory, + Value branch = const Value.absent(), + String? status, + DateTime? createdAt, + Value lastMessageAt = const Value.absent(), + DateTime? updatedAt, + bool? synced}) => + Session( + id: id ?? this.id, + agentType: agentType ?? this.agentType, + agentId: agentId.present ? agentId.value : this.agentId, + title: title ?? this.title, + workingDirectory: workingDirectory ?? this.workingDirectory, + branch: branch.present ? branch.value : this.branch, + status: status ?? this.status, + createdAt: createdAt ?? this.createdAt, + lastMessageAt: + lastMessageAt.present ? lastMessageAt.value : this.lastMessageAt, + updatedAt: updatedAt ?? this.updatedAt, + synced: synced ?? this.synced, + ); + Session copyWithCompanion(SessionsCompanion data) { + return Session( + id: data.id.present ? data.id.value : this.id, + agentType: data.agentType.present ? data.agentType.value : this.agentType, + agentId: data.agentId.present ? data.agentId.value : this.agentId, + title: data.title.present ? data.title.value : this.title, + workingDirectory: data.workingDirectory.present + ? data.workingDirectory.value + : this.workingDirectory, + branch: data.branch.present ? data.branch.value : this.branch, + status: data.status.present ? data.status.value : this.status, + createdAt: data.createdAt.present ? data.createdAt.value : this.createdAt, + lastMessageAt: data.lastMessageAt.present + ? data.lastMessageAt.value + : this.lastMessageAt, + updatedAt: data.updatedAt.present ? data.updatedAt.value : this.updatedAt, + synced: data.synced.present ? data.synced.value : this.synced, + ); + } + + @override + String toString() { + return (StringBuffer('Session(') + ..write('id: $id, ') + ..write('agentType: $agentType, ') + ..write('agentId: $agentId, ') + ..write('title: $title, ') + ..write('workingDirectory: $workingDirectory, ') + ..write('branch: $branch, ') + ..write('status: $status, ') + ..write('createdAt: $createdAt, ') + ..write('lastMessageAt: $lastMessageAt, ') + ..write('updatedAt: $updatedAt, ') + ..write('synced: $synced') + ..write(')')) + .toString(); + } + + @override + int get hashCode => Object.hash( + id, + agentType, + agentId, + title, + workingDirectory, + branch, + status, + createdAt, + lastMessageAt, + updatedAt, + synced); + @override + bool operator ==(Object other) => + identical(this, other) || + (other is Session && + other.id == this.id && + other.agentType == this.agentType && + other.agentId == this.agentId && + other.title == this.title && + other.workingDirectory == this.workingDirectory && + other.branch == this.branch && + other.status == this.status && + other.createdAt == this.createdAt && + other.lastMessageAt == this.lastMessageAt && + other.updatedAt == this.updatedAt && + other.synced == this.synced); +} + +class SessionsCompanion extends UpdateCompanion { + final Value id; + final Value agentType; + final Value agentId; + final Value title; + final Value workingDirectory; + final Value branch; + final Value status; + final Value createdAt; + final Value lastMessageAt; + final Value updatedAt; + final Value synced; + final Value rowid; + const SessionsCompanion({ + this.id = const Value.absent(), + this.agentType = const Value.absent(), + this.agentId = const Value.absent(), + this.title = const Value.absent(), + this.workingDirectory = const Value.absent(), + this.branch = const Value.absent(), + this.status = const Value.absent(), + this.createdAt = const Value.absent(), + this.lastMessageAt = const Value.absent(), + this.updatedAt = const Value.absent(), + this.synced = const Value.absent(), + this.rowid = const Value.absent(), + }); + SessionsCompanion.insert({ + required String id, + required String agentType, + this.agentId = const Value.absent(), + this.title = const Value.absent(), + required String workingDirectory, + this.branch = const Value.absent(), + required String status, + required DateTime createdAt, + this.lastMessageAt = const Value.absent(), + required DateTime updatedAt, + this.synced = const Value.absent(), + this.rowid = const Value.absent(), + }) : id = Value(id), + agentType = Value(agentType), + workingDirectory = Value(workingDirectory), + status = Value(status), + createdAt = Value(createdAt), + updatedAt = Value(updatedAt); + static Insertable custom({ + Expression? id, + Expression? agentType, + Expression? agentId, + Expression? title, + Expression? workingDirectory, + Expression? branch, + Expression? status, + Expression? createdAt, + Expression? lastMessageAt, + Expression? updatedAt, + Expression? synced, + Expression? rowid, + }) { + return RawValuesInsertable({ + if (id != null) 'id': id, + if (agentType != null) 'agent_type': agentType, + if (agentId != null) 'agent_id': agentId, + if (title != null) 'title': title, + if (workingDirectory != null) 'working_directory': workingDirectory, + if (branch != null) 'branch': branch, + if (status != null) 'status': status, + if (createdAt != null) 'created_at': createdAt, + if (lastMessageAt != null) 'last_message_at': lastMessageAt, + if (updatedAt != null) 'updated_at': updatedAt, + if (synced != null) 'synced': synced, + if (rowid != null) 'rowid': rowid, + }); + } + + SessionsCompanion copyWith( + {Value? id, + Value? agentType, + Value? agentId, + Value? title, + Value? workingDirectory, + Value? branch, + Value? status, + Value? createdAt, + Value? lastMessageAt, + Value? updatedAt, + Value? synced, + Value? rowid}) { + return SessionsCompanion( + id: id ?? this.id, + agentType: agentType ?? this.agentType, + agentId: agentId ?? this.agentId, + title: title ?? this.title, + workingDirectory: workingDirectory ?? this.workingDirectory, + branch: branch ?? this.branch, + status: status ?? this.status, + createdAt: createdAt ?? this.createdAt, + lastMessageAt: lastMessageAt ?? this.lastMessageAt, + updatedAt: updatedAt ?? this.updatedAt, + synced: synced ?? this.synced, + rowid: rowid ?? this.rowid, + ); + } + + @override + Map toColumns(bool nullToAbsent) { + final map = {}; + if (id.present) { + map['id'] = Variable(id.value); + } + if (agentType.present) { + map['agent_type'] = Variable(agentType.value); + } + if (agentId.present) { + map['agent_id'] = Variable(agentId.value); + } + if (title.present) { + map['title'] = Variable(title.value); + } + if (workingDirectory.present) { + map['working_directory'] = Variable(workingDirectory.value); + } + if (branch.present) { + map['branch'] = Variable(branch.value); + } + if (status.present) { + map['status'] = Variable(status.value); + } + if (createdAt.present) { + map['created_at'] = Variable(createdAt.value); + } + if (lastMessageAt.present) { + map['last_message_at'] = Variable(lastMessageAt.value); + } + if (updatedAt.present) { + map['updated_at'] = Variable(updatedAt.value); + } + if (synced.present) { + map['synced'] = Variable(synced.value); + } + if (rowid.present) { + map['rowid'] = Variable(rowid.value); + } + return map; + } + + @override + String toString() { + return (StringBuffer('SessionsCompanion(') + ..write('id: $id, ') + ..write('agentType: $agentType, ') + ..write('agentId: $agentId, ') + ..write('title: $title, ') + ..write('workingDirectory: $workingDirectory, ') + ..write('branch: $branch, ') + ..write('status: $status, ') + ..write('createdAt: $createdAt, ') + ..write('lastMessageAt: $lastMessageAt, ') + ..write('updatedAt: $updatedAt, ') + ..write('synced: $synced, ') + ..write('rowid: $rowid') + ..write(')')) + .toString(); + } +} + +class $MessagesTable extends Messages with TableInfo<$MessagesTable, Message> { + @override + final GeneratedDatabase attachedDatabase; + final String? _alias; + $MessagesTable(this.attachedDatabase, [this._alias]); + static const VerificationMeta _idMeta = const VerificationMeta('id'); + @override + late final GeneratedColumn id = GeneratedColumn( + 'id', aliasedName, false, + type: DriftSqlType.string, requiredDuringInsert: true); + static const VerificationMeta _sessionIdMeta = + const VerificationMeta('sessionId'); + @override + late final GeneratedColumn sessionId = GeneratedColumn( + 'session_id', aliasedName, false, + type: DriftSqlType.string, + requiredDuringInsert: true, + defaultConstraints: + GeneratedColumn.constraintIsAlways('REFERENCES sessions (id)')); + static const VerificationMeta _roleMeta = const VerificationMeta('role'); + @override + late final GeneratedColumn role = GeneratedColumn( + 'role', aliasedName, false, + type: DriftSqlType.string, requiredDuringInsert: true); + static const VerificationMeta _contentMeta = + const VerificationMeta('content'); + @override + late final GeneratedColumn content = GeneratedColumn( + 'content', aliasedName, false, + type: DriftSqlType.string, requiredDuringInsert: true); + static const VerificationMeta _messageTypeMeta = + const VerificationMeta('messageType'); + @override + late final GeneratedColumn messageType = GeneratedColumn( + 'message_type', aliasedName, false, + type: DriftSqlType.string, + requiredDuringInsert: false, + defaultValue: const Constant('text')); + static const VerificationMeta _metadataMeta = + const VerificationMeta('metadata'); + @override + late final GeneratedColumn metadata = GeneratedColumn( + 'metadata', aliasedName, true, + type: DriftSqlType.string, requiredDuringInsert: false); + static const VerificationMeta _createdAtMeta = + const VerificationMeta('createdAt'); + @override + late final GeneratedColumn createdAt = GeneratedColumn( + 'created_at', aliasedName, false, + type: DriftSqlType.dateTime, requiredDuringInsert: true); + static const VerificationMeta _updatedAtMeta = + const VerificationMeta('updatedAt'); + @override + late final GeneratedColumn updatedAt = GeneratedColumn( + 'updated_at', aliasedName, false, + type: DriftSqlType.dateTime, requiredDuringInsert: true); + static const VerificationMeta _syncedMeta = const VerificationMeta('synced'); + @override + late final GeneratedColumn synced = GeneratedColumn( + 'synced', aliasedName, false, + type: DriftSqlType.bool, + requiredDuringInsert: false, + defaultConstraints: + GeneratedColumn.constraintIsAlways('CHECK ("synced" IN (0, 1))'), + defaultValue: const Constant(true)); + @override + List get $columns => [ + id, + sessionId, + role, + content, + messageType, + metadata, + createdAt, + updatedAt, + synced + ]; + @override + String get aliasedName => _alias ?? actualTableName; + @override + String get actualTableName => $name; + static const String $name = 'messages'; + @override + VerificationContext validateIntegrity(Insertable instance, + {bool isInserting = false}) { + final context = VerificationContext(); + final data = instance.toColumns(true); + if (data.containsKey('id')) { + context.handle(_idMeta, id.isAcceptableOrUnknown(data['id']!, _idMeta)); + } else if (isInserting) { + context.missing(_idMeta); + } + if (data.containsKey('session_id')) { + context.handle(_sessionIdMeta, + sessionId.isAcceptableOrUnknown(data['session_id']!, _sessionIdMeta)); + } else if (isInserting) { + context.missing(_sessionIdMeta); + } + if (data.containsKey('role')) { + context.handle( + _roleMeta, role.isAcceptableOrUnknown(data['role']!, _roleMeta)); + } else if (isInserting) { + context.missing(_roleMeta); + } + if (data.containsKey('content')) { + context.handle(_contentMeta, + content.isAcceptableOrUnknown(data['content']!, _contentMeta)); + } else if (isInserting) { + context.missing(_contentMeta); + } + if (data.containsKey('message_type')) { + context.handle( + _messageTypeMeta, + messageType.isAcceptableOrUnknown( + data['message_type']!, _messageTypeMeta)); + } + if (data.containsKey('metadata')) { + context.handle(_metadataMeta, + metadata.isAcceptableOrUnknown(data['metadata']!, _metadataMeta)); + } + if (data.containsKey('created_at')) { + context.handle(_createdAtMeta, + createdAt.isAcceptableOrUnknown(data['created_at']!, _createdAtMeta)); + } else if (isInserting) { + context.missing(_createdAtMeta); + } + if (data.containsKey('updated_at')) { + context.handle(_updatedAtMeta, + updatedAt.isAcceptableOrUnknown(data['updated_at']!, _updatedAtMeta)); + } else if (isInserting) { + context.missing(_updatedAtMeta); + } + if (data.containsKey('synced')) { + context.handle(_syncedMeta, + synced.isAcceptableOrUnknown(data['synced']!, _syncedMeta)); + } + return context; + } + + @override + Set get $primaryKey => {id}; + @override + Message map(Map data, {String? tablePrefix}) { + final effectivePrefix = tablePrefix != null ? '$tablePrefix.' : ''; + return Message( + id: attachedDatabase.typeMapping + .read(DriftSqlType.string, data['${effectivePrefix}id'])!, + sessionId: attachedDatabase.typeMapping + .read(DriftSqlType.string, data['${effectivePrefix}session_id'])!, + role: attachedDatabase.typeMapping + .read(DriftSqlType.string, data['${effectivePrefix}role'])!, + content: attachedDatabase.typeMapping + .read(DriftSqlType.string, data['${effectivePrefix}content'])!, + messageType: attachedDatabase.typeMapping + .read(DriftSqlType.string, data['${effectivePrefix}message_type'])!, + metadata: attachedDatabase.typeMapping + .read(DriftSqlType.string, data['${effectivePrefix}metadata']), + createdAt: attachedDatabase.typeMapping + .read(DriftSqlType.dateTime, data['${effectivePrefix}created_at'])!, + updatedAt: attachedDatabase.typeMapping + .read(DriftSqlType.dateTime, data['${effectivePrefix}updated_at'])!, + synced: attachedDatabase.typeMapping + .read(DriftSqlType.bool, data['${effectivePrefix}synced'])!, + ); + } + + @override + $MessagesTable createAlias(String alias) { + return $MessagesTable(attachedDatabase, alias); + } +} + +class Message extends DataClass implements Insertable { + final String id; + final String sessionId; + + /// "user" | "agent" | "system" + final String role; + + /// Full message text (markdown). + final String content; + + /// "text" | "tool_call" | "tool_result" | "system" + final String messageType; + + /// JSON: token count, tool info, etc. + final String? metadata; + final DateTime createdAt; + final DateTime updatedAt; + final bool synced; + const Message( + {required this.id, + required this.sessionId, + required this.role, + required this.content, + required this.messageType, + this.metadata, + required this.createdAt, + required this.updatedAt, + required this.synced}); + @override + Map toColumns(bool nullToAbsent) { + final map = {}; + map['id'] = Variable(id); + map['session_id'] = Variable(sessionId); + map['role'] = Variable(role); + map['content'] = Variable(content); + map['message_type'] = Variable(messageType); + if (!nullToAbsent || metadata != null) { + map['metadata'] = Variable(metadata); + } + map['created_at'] = Variable(createdAt); + map['updated_at'] = Variable(updatedAt); + map['synced'] = Variable(synced); + return map; + } + + MessagesCompanion toCompanion(bool nullToAbsent) { + return MessagesCompanion( + id: Value(id), + sessionId: Value(sessionId), + role: Value(role), + content: Value(content), + messageType: Value(messageType), + metadata: metadata == null && nullToAbsent + ? const Value.absent() + : Value(metadata), + createdAt: Value(createdAt), + updatedAt: Value(updatedAt), + synced: Value(synced), + ); + } + + factory Message.fromJson(Map json, + {ValueSerializer? serializer}) { + serializer ??= driftRuntimeOptions.defaultSerializer; + return Message( + id: serializer.fromJson(json['id']), + sessionId: serializer.fromJson(json['sessionId']), + role: serializer.fromJson(json['role']), + content: serializer.fromJson(json['content']), + messageType: serializer.fromJson(json['messageType']), + metadata: serializer.fromJson(json['metadata']), + createdAt: serializer.fromJson(json['createdAt']), + updatedAt: serializer.fromJson(json['updatedAt']), + synced: serializer.fromJson(json['synced']), + ); + } + @override + Map toJson({ValueSerializer? serializer}) { + serializer ??= driftRuntimeOptions.defaultSerializer; + return { + 'id': serializer.toJson(id), + 'sessionId': serializer.toJson(sessionId), + 'role': serializer.toJson(role), + 'content': serializer.toJson(content), + 'messageType': serializer.toJson(messageType), + 'metadata': serializer.toJson(metadata), + 'createdAt': serializer.toJson(createdAt), + 'updatedAt': serializer.toJson(updatedAt), + 'synced': serializer.toJson(synced), + }; + } + + Message copyWith( + {String? id, + String? sessionId, + String? role, + String? content, + String? messageType, + Value metadata = const Value.absent(), + DateTime? createdAt, + DateTime? updatedAt, + bool? synced}) => + Message( + id: id ?? this.id, + sessionId: sessionId ?? this.sessionId, + role: role ?? this.role, + content: content ?? this.content, + messageType: messageType ?? this.messageType, + metadata: metadata.present ? metadata.value : this.metadata, + createdAt: createdAt ?? this.createdAt, + updatedAt: updatedAt ?? this.updatedAt, + synced: synced ?? this.synced, + ); + Message copyWithCompanion(MessagesCompanion data) { + return Message( + id: data.id.present ? data.id.value : this.id, + sessionId: data.sessionId.present ? data.sessionId.value : this.sessionId, + role: data.role.present ? data.role.value : this.role, + content: data.content.present ? data.content.value : this.content, + messageType: + data.messageType.present ? data.messageType.value : this.messageType, + metadata: data.metadata.present ? data.metadata.value : this.metadata, + createdAt: data.createdAt.present ? data.createdAt.value : this.createdAt, + updatedAt: data.updatedAt.present ? data.updatedAt.value : this.updatedAt, + synced: data.synced.present ? data.synced.value : this.synced, + ); + } + + @override + String toString() { + return (StringBuffer('Message(') + ..write('id: $id, ') + ..write('sessionId: $sessionId, ') + ..write('role: $role, ') + ..write('content: $content, ') + ..write('messageType: $messageType, ') + ..write('metadata: $metadata, ') + ..write('createdAt: $createdAt, ') + ..write('updatedAt: $updatedAt, ') + ..write('synced: $synced') + ..write(')')) + .toString(); + } + + @override + int get hashCode => Object.hash(id, sessionId, role, content, messageType, + metadata, createdAt, updatedAt, synced); + @override + bool operator ==(Object other) => + identical(this, other) || + (other is Message && + other.id == this.id && + other.sessionId == this.sessionId && + other.role == this.role && + other.content == this.content && + other.messageType == this.messageType && + other.metadata == this.metadata && + other.createdAt == this.createdAt && + other.updatedAt == this.updatedAt && + other.synced == this.synced); +} + +class MessagesCompanion extends UpdateCompanion { + final Value id; + final Value sessionId; + final Value role; + final Value content; + final Value messageType; + final Value metadata; + final Value createdAt; + final Value updatedAt; + final Value synced; + final Value rowid; + const MessagesCompanion({ + this.id = const Value.absent(), + this.sessionId = const Value.absent(), + this.role = const Value.absent(), + this.content = const Value.absent(), + this.messageType = const Value.absent(), + this.metadata = const Value.absent(), + this.createdAt = const Value.absent(), + this.updatedAt = const Value.absent(), + this.synced = const Value.absent(), + this.rowid = const Value.absent(), + }); + MessagesCompanion.insert({ + required String id, + required String sessionId, + required String role, + required String content, + this.messageType = const Value.absent(), + this.metadata = const Value.absent(), + required DateTime createdAt, + required DateTime updatedAt, + this.synced = const Value.absent(), + this.rowid = const Value.absent(), + }) : id = Value(id), + sessionId = Value(sessionId), + role = Value(role), + content = Value(content), + createdAt = Value(createdAt), + updatedAt = Value(updatedAt); + static Insertable custom({ + Expression? id, + Expression? sessionId, + Expression? role, + Expression? content, + Expression? messageType, + Expression? metadata, + Expression? createdAt, + Expression? updatedAt, + Expression? synced, + Expression? rowid, + }) { + return RawValuesInsertable({ + if (id != null) 'id': id, + if (sessionId != null) 'session_id': sessionId, + if (role != null) 'role': role, + if (content != null) 'content': content, + if (messageType != null) 'message_type': messageType, + if (metadata != null) 'metadata': metadata, + if (createdAt != null) 'created_at': createdAt, + if (updatedAt != null) 'updated_at': updatedAt, + if (synced != null) 'synced': synced, + if (rowid != null) 'rowid': rowid, + }); + } + + MessagesCompanion copyWith( + {Value? id, + Value? sessionId, + Value? role, + Value? content, + Value? messageType, + Value? metadata, + Value? createdAt, + Value? updatedAt, + Value? synced, + Value? rowid}) { + return MessagesCompanion( + id: id ?? this.id, + sessionId: sessionId ?? this.sessionId, + role: role ?? this.role, + content: content ?? this.content, + messageType: messageType ?? this.messageType, + metadata: metadata ?? this.metadata, + createdAt: createdAt ?? this.createdAt, + updatedAt: updatedAt ?? this.updatedAt, + synced: synced ?? this.synced, + rowid: rowid ?? this.rowid, + ); + } + + @override + Map toColumns(bool nullToAbsent) { + final map = {}; + if (id.present) { + map['id'] = Variable(id.value); + } + if (sessionId.present) { + map['session_id'] = Variable(sessionId.value); + } + if (role.present) { + map['role'] = Variable(role.value); + } + if (content.present) { + map['content'] = Variable(content.value); + } + if (messageType.present) { + map['message_type'] = Variable(messageType.value); + } + if (metadata.present) { + map['metadata'] = Variable(metadata.value); + } + if (createdAt.present) { + map['created_at'] = Variable(createdAt.value); + } + if (updatedAt.present) { + map['updated_at'] = Variable(updatedAt.value); + } + if (synced.present) { + map['synced'] = Variable(synced.value); + } + if (rowid.present) { + map['rowid'] = Variable(rowid.value); + } + return map; + } + + @override + String toString() { + return (StringBuffer('MessagesCompanion(') + ..write('id: $id, ') + ..write('sessionId: $sessionId, ') + ..write('role: $role, ') + ..write('content: $content, ') + ..write('messageType: $messageType, ') + ..write('metadata: $metadata, ') + ..write('createdAt: $createdAt, ') + ..write('updatedAt: $updatedAt, ') + ..write('synced: $synced, ') + ..write('rowid: $rowid') + ..write(')')) + .toString(); + } +} + +class $AgentsTable extends Agents with TableInfo<$AgentsTable, Agent> { + @override + final GeneratedDatabase attachedDatabase; + final String? _alias; + $AgentsTable(this.attachedDatabase, [this._alias]); + static const VerificationMeta _idMeta = const VerificationMeta('id'); + @override + late final GeneratedColumn id = GeneratedColumn( + 'id', aliasedName, false, + type: DriftSqlType.string, requiredDuringInsert: true); + static const VerificationMeta _displayNameMeta = + const VerificationMeta('displayName'); + @override + late final GeneratedColumn displayName = GeneratedColumn( + 'display_name', aliasedName, false, + type: DriftSqlType.string, requiredDuringInsert: true); + static const VerificationMeta _agentTypeMeta = + const VerificationMeta('agentType'); + @override + late final GeneratedColumn agentType = GeneratedColumn( + 'agent_type', aliasedName, false, + type: DriftSqlType.string, requiredDuringInsert: true); + static const VerificationMeta _bridgeUrlMeta = + const VerificationMeta('bridgeUrl'); + @override + late final GeneratedColumn bridgeUrl = GeneratedColumn( + 'bridge_url', aliasedName, false, + type: DriftSqlType.string, requiredDuringInsert: true); + static const VerificationMeta _authTokenMeta = + const VerificationMeta('authToken'); + @override + late final GeneratedColumn authToken = GeneratedColumn( + 'auth_token', aliasedName, false, + type: DriftSqlType.string, requiredDuringInsert: true); + static const VerificationMeta _workingDirectoryMeta = + const VerificationMeta('workingDirectory'); + @override + late final GeneratedColumn workingDirectory = GeneratedColumn( + 'working_directory', aliasedName, true, + type: DriftSqlType.string, requiredDuringInsert: false); + static const VerificationMeta _statusMeta = const VerificationMeta('status'); + @override + late final GeneratedColumn status = GeneratedColumn( + 'status', aliasedName, false, + type: DriftSqlType.string, + requiredDuringInsert: false, + defaultValue: const Constant('disconnected')); + static const VerificationMeta _lastConnectedAtMeta = + const VerificationMeta('lastConnectedAt'); + @override + late final GeneratedColumn lastConnectedAt = + GeneratedColumn('last_connected_at', aliasedName, true, + type: DriftSqlType.dateTime, requiredDuringInsert: false); + static const VerificationMeta _createdAtMeta = + const VerificationMeta('createdAt'); + @override + late final GeneratedColumn createdAt = GeneratedColumn( + 'created_at', aliasedName, false, + type: DriftSqlType.dateTime, requiredDuringInsert: true); + static const VerificationMeta _updatedAtMeta = + const VerificationMeta('updatedAt'); + @override + late final GeneratedColumn updatedAt = GeneratedColumn( + 'updated_at', aliasedName, false, + type: DriftSqlType.dateTime, requiredDuringInsert: true); + @override + List get $columns => [ + id, + displayName, + agentType, + bridgeUrl, + authToken, + workingDirectory, + status, + lastConnectedAt, + createdAt, + updatedAt + ]; + @override + String get aliasedName => _alias ?? actualTableName; + @override + String get actualTableName => $name; + static const String $name = 'agents'; + @override + VerificationContext validateIntegrity(Insertable instance, + {bool isInserting = false}) { + final context = VerificationContext(); + final data = instance.toColumns(true); + if (data.containsKey('id')) { + context.handle(_idMeta, id.isAcceptableOrUnknown(data['id']!, _idMeta)); + } else if (isInserting) { + context.missing(_idMeta); + } + if (data.containsKey('display_name')) { + context.handle( + _displayNameMeta, + displayName.isAcceptableOrUnknown( + data['display_name']!, _displayNameMeta)); + } else if (isInserting) { + context.missing(_displayNameMeta); + } + if (data.containsKey('agent_type')) { + context.handle(_agentTypeMeta, + agentType.isAcceptableOrUnknown(data['agent_type']!, _agentTypeMeta)); + } else if (isInserting) { + context.missing(_agentTypeMeta); + } + if (data.containsKey('bridge_url')) { + context.handle(_bridgeUrlMeta, + bridgeUrl.isAcceptableOrUnknown(data['bridge_url']!, _bridgeUrlMeta)); + } else if (isInserting) { + context.missing(_bridgeUrlMeta); + } + if (data.containsKey('auth_token')) { + context.handle(_authTokenMeta, + authToken.isAcceptableOrUnknown(data['auth_token']!, _authTokenMeta)); + } else if (isInserting) { + context.missing(_authTokenMeta); + } + if (data.containsKey('working_directory')) { + context.handle( + _workingDirectoryMeta, + workingDirectory.isAcceptableOrUnknown( + data['working_directory']!, _workingDirectoryMeta)); + } + if (data.containsKey('status')) { + context.handle(_statusMeta, + status.isAcceptableOrUnknown(data['status']!, _statusMeta)); + } + if (data.containsKey('last_connected_at')) { + context.handle( + _lastConnectedAtMeta, + lastConnectedAt.isAcceptableOrUnknown( + data['last_connected_at']!, _lastConnectedAtMeta)); + } + if (data.containsKey('created_at')) { + context.handle(_createdAtMeta, + createdAt.isAcceptableOrUnknown(data['created_at']!, _createdAtMeta)); + } else if (isInserting) { + context.missing(_createdAtMeta); + } + if (data.containsKey('updated_at')) { + context.handle(_updatedAtMeta, + updatedAt.isAcceptableOrUnknown(data['updated_at']!, _updatedAtMeta)); + } else if (isInserting) { + context.missing(_updatedAtMeta); + } + return context; + } + + @override + Set get $primaryKey => {id}; + @override + Agent map(Map data, {String? tablePrefix}) { + final effectivePrefix = tablePrefix != null ? '$tablePrefix.' : ''; + return Agent( + id: attachedDatabase.typeMapping + .read(DriftSqlType.string, data['${effectivePrefix}id'])!, + displayName: attachedDatabase.typeMapping + .read(DriftSqlType.string, data['${effectivePrefix}display_name'])!, + agentType: attachedDatabase.typeMapping + .read(DriftSqlType.string, data['${effectivePrefix}agent_type'])!, + bridgeUrl: attachedDatabase.typeMapping + .read(DriftSqlType.string, data['${effectivePrefix}bridge_url'])!, + authToken: attachedDatabase.typeMapping + .read(DriftSqlType.string, data['${effectivePrefix}auth_token'])!, + workingDirectory: attachedDatabase.typeMapping.read( + DriftSqlType.string, data['${effectivePrefix}working_directory']), + status: attachedDatabase.typeMapping + .read(DriftSqlType.string, data['${effectivePrefix}status'])!, + lastConnectedAt: attachedDatabase.typeMapping.read( + DriftSqlType.dateTime, data['${effectivePrefix}last_connected_at']), + createdAt: attachedDatabase.typeMapping + .read(DriftSqlType.dateTime, data['${effectivePrefix}created_at'])!, + updatedAt: attachedDatabase.typeMapping + .read(DriftSqlType.dateTime, data['${effectivePrefix}updated_at'])!, + ); + } + + @override + $AgentsTable createAlias(String alias) { + return $AgentsTable(attachedDatabase, alias); + } +} + +class Agent extends DataClass implements Insertable { + final String id; + final String displayName; + + /// "claude-code" | "opencode" | "aider" | "goose" | "custom" + final String agentType; + + /// WebSocket bridge URL, e.g. "wss://100.78.42.15:3000" + final String bridgeUrl; + + /// Encrypted bridge auth token. + final String authToken; + final String? workingDirectory; + + /// "connected" | "disconnected" | "inactive" + final String status; + final DateTime? lastConnectedAt; + final DateTime createdAt; + final DateTime updatedAt; + const Agent( + {required this.id, + required this.displayName, + required this.agentType, + required this.bridgeUrl, + required this.authToken, + this.workingDirectory, + required this.status, + this.lastConnectedAt, + required this.createdAt, + required this.updatedAt}); + @override + Map toColumns(bool nullToAbsent) { + final map = {}; + map['id'] = Variable(id); + map['display_name'] = Variable(displayName); + map['agent_type'] = Variable(agentType); + map['bridge_url'] = Variable(bridgeUrl); + map['auth_token'] = Variable(authToken); + if (!nullToAbsent || workingDirectory != null) { + map['working_directory'] = Variable(workingDirectory); + } + map['status'] = Variable(status); + if (!nullToAbsent || lastConnectedAt != null) { + map['last_connected_at'] = Variable(lastConnectedAt); + } + map['created_at'] = Variable(createdAt); + map['updated_at'] = Variable(updatedAt); + return map; + } + + AgentsCompanion toCompanion(bool nullToAbsent) { + return AgentsCompanion( + id: Value(id), + displayName: Value(displayName), + agentType: Value(agentType), + bridgeUrl: Value(bridgeUrl), + authToken: Value(authToken), + workingDirectory: workingDirectory == null && nullToAbsent + ? const Value.absent() + : Value(workingDirectory), + status: Value(status), + lastConnectedAt: lastConnectedAt == null && nullToAbsent + ? const Value.absent() + : Value(lastConnectedAt), + createdAt: Value(createdAt), + updatedAt: Value(updatedAt), + ); + } + + factory Agent.fromJson(Map json, + {ValueSerializer? serializer}) { + serializer ??= driftRuntimeOptions.defaultSerializer; + return Agent( + id: serializer.fromJson(json['id']), + displayName: serializer.fromJson(json['displayName']), + agentType: serializer.fromJson(json['agentType']), + bridgeUrl: serializer.fromJson(json['bridgeUrl']), + authToken: serializer.fromJson(json['authToken']), + workingDirectory: serializer.fromJson(json['workingDirectory']), + status: serializer.fromJson(json['status']), + lastConnectedAt: serializer.fromJson(json['lastConnectedAt']), + createdAt: serializer.fromJson(json['createdAt']), + updatedAt: serializer.fromJson(json['updatedAt']), + ); + } + @override + Map toJson({ValueSerializer? serializer}) { + serializer ??= driftRuntimeOptions.defaultSerializer; + return { + 'id': serializer.toJson(id), + 'displayName': serializer.toJson(displayName), + 'agentType': serializer.toJson(agentType), + 'bridgeUrl': serializer.toJson(bridgeUrl), + 'authToken': serializer.toJson(authToken), + 'workingDirectory': serializer.toJson(workingDirectory), + 'status': serializer.toJson(status), + 'lastConnectedAt': serializer.toJson(lastConnectedAt), + 'createdAt': serializer.toJson(createdAt), + 'updatedAt': serializer.toJson(updatedAt), + }; + } + + Agent copyWith( + {String? id, + String? displayName, + String? agentType, + String? bridgeUrl, + String? authToken, + Value workingDirectory = const Value.absent(), + String? status, + Value lastConnectedAt = const Value.absent(), + DateTime? createdAt, + DateTime? updatedAt}) => + Agent( + id: id ?? this.id, + displayName: displayName ?? this.displayName, + agentType: agentType ?? this.agentType, + bridgeUrl: bridgeUrl ?? this.bridgeUrl, + authToken: authToken ?? this.authToken, + workingDirectory: workingDirectory.present + ? workingDirectory.value + : this.workingDirectory, + status: status ?? this.status, + lastConnectedAt: lastConnectedAt.present + ? lastConnectedAt.value + : this.lastConnectedAt, + createdAt: createdAt ?? this.createdAt, + updatedAt: updatedAt ?? this.updatedAt, + ); + Agent copyWithCompanion(AgentsCompanion data) { + return Agent( + id: data.id.present ? data.id.value : this.id, + displayName: + data.displayName.present ? data.displayName.value : this.displayName, + agentType: data.agentType.present ? data.agentType.value : this.agentType, + bridgeUrl: data.bridgeUrl.present ? data.bridgeUrl.value : this.bridgeUrl, + authToken: data.authToken.present ? data.authToken.value : this.authToken, + workingDirectory: data.workingDirectory.present + ? data.workingDirectory.value + : this.workingDirectory, + status: data.status.present ? data.status.value : this.status, + lastConnectedAt: data.lastConnectedAt.present + ? data.lastConnectedAt.value + : this.lastConnectedAt, + createdAt: data.createdAt.present ? data.createdAt.value : this.createdAt, + updatedAt: data.updatedAt.present ? data.updatedAt.value : this.updatedAt, + ); + } + + @override + String toString() { + return (StringBuffer('Agent(') + ..write('id: $id, ') + ..write('displayName: $displayName, ') + ..write('agentType: $agentType, ') + ..write('bridgeUrl: $bridgeUrl, ') + ..write('authToken: $authToken, ') + ..write('workingDirectory: $workingDirectory, ') + ..write('status: $status, ') + ..write('lastConnectedAt: $lastConnectedAt, ') + ..write('createdAt: $createdAt, ') + ..write('updatedAt: $updatedAt') + ..write(')')) + .toString(); + } + + @override + int get hashCode => Object.hash( + id, + displayName, + agentType, + bridgeUrl, + authToken, + workingDirectory, + status, + lastConnectedAt, + createdAt, + updatedAt); + @override + bool operator ==(Object other) => + identical(this, other) || + (other is Agent && + other.id == this.id && + other.displayName == this.displayName && + other.agentType == this.agentType && + other.bridgeUrl == this.bridgeUrl && + other.authToken == this.authToken && + other.workingDirectory == this.workingDirectory && + other.status == this.status && + other.lastConnectedAt == this.lastConnectedAt && + other.createdAt == this.createdAt && + other.updatedAt == this.updatedAt); +} + +class AgentsCompanion extends UpdateCompanion { + final Value id; + final Value displayName; + final Value agentType; + final Value bridgeUrl; + final Value authToken; + final Value workingDirectory; + final Value status; + final Value lastConnectedAt; + final Value createdAt; + final Value updatedAt; + final Value rowid; + const AgentsCompanion({ + this.id = const Value.absent(), + this.displayName = const Value.absent(), + this.agentType = const Value.absent(), + this.bridgeUrl = const Value.absent(), + this.authToken = const Value.absent(), + this.workingDirectory = const Value.absent(), + this.status = const Value.absent(), + this.lastConnectedAt = const Value.absent(), + this.createdAt = const Value.absent(), + this.updatedAt = const Value.absent(), + this.rowid = const Value.absent(), + }); + AgentsCompanion.insert({ + required String id, + required String displayName, + required String agentType, + required String bridgeUrl, + required String authToken, + this.workingDirectory = const Value.absent(), + this.status = const Value.absent(), + this.lastConnectedAt = const Value.absent(), + required DateTime createdAt, + required DateTime updatedAt, + this.rowid = const Value.absent(), + }) : id = Value(id), + displayName = Value(displayName), + agentType = Value(agentType), + bridgeUrl = Value(bridgeUrl), + authToken = Value(authToken), + createdAt = Value(createdAt), + updatedAt = Value(updatedAt); + static Insertable custom({ + Expression? id, + Expression? displayName, + Expression? agentType, + Expression? bridgeUrl, + Expression? authToken, + Expression? workingDirectory, + Expression? status, + Expression? lastConnectedAt, + Expression? createdAt, + Expression? updatedAt, + Expression? rowid, + }) { + return RawValuesInsertable({ + if (id != null) 'id': id, + if (displayName != null) 'display_name': displayName, + if (agentType != null) 'agent_type': agentType, + if (bridgeUrl != null) 'bridge_url': bridgeUrl, + if (authToken != null) 'auth_token': authToken, + if (workingDirectory != null) 'working_directory': workingDirectory, + if (status != null) 'status': status, + if (lastConnectedAt != null) 'last_connected_at': lastConnectedAt, + if (createdAt != null) 'created_at': createdAt, + if (updatedAt != null) 'updated_at': updatedAt, + if (rowid != null) 'rowid': rowid, + }); + } + + AgentsCompanion copyWith( + {Value? id, + Value? displayName, + Value? agentType, + Value? bridgeUrl, + Value? authToken, + Value? workingDirectory, + Value? status, + Value? lastConnectedAt, + Value? createdAt, + Value? updatedAt, + Value? rowid}) { + return AgentsCompanion( + id: id ?? this.id, + displayName: displayName ?? this.displayName, + agentType: agentType ?? this.agentType, + bridgeUrl: bridgeUrl ?? this.bridgeUrl, + authToken: authToken ?? this.authToken, + workingDirectory: workingDirectory ?? this.workingDirectory, + status: status ?? this.status, + lastConnectedAt: lastConnectedAt ?? this.lastConnectedAt, + createdAt: createdAt ?? this.createdAt, + updatedAt: updatedAt ?? this.updatedAt, + rowid: rowid ?? this.rowid, + ); + } + + @override + Map toColumns(bool nullToAbsent) { + final map = {}; + if (id.present) { + map['id'] = Variable(id.value); + } + if (displayName.present) { + map['display_name'] = Variable(displayName.value); + } + if (agentType.present) { + map['agent_type'] = Variable(agentType.value); + } + if (bridgeUrl.present) { + map['bridge_url'] = Variable(bridgeUrl.value); + } + if (authToken.present) { + map['auth_token'] = Variable(authToken.value); + } + if (workingDirectory.present) { + map['working_directory'] = Variable(workingDirectory.value); + } + if (status.present) { + map['status'] = Variable(status.value); + } + if (lastConnectedAt.present) { + map['last_connected_at'] = Variable(lastConnectedAt.value); + } + if (createdAt.present) { + map['created_at'] = Variable(createdAt.value); + } + if (updatedAt.present) { + map['updated_at'] = Variable(updatedAt.value); + } + if (rowid.present) { + map['rowid'] = Variable(rowid.value); + } + return map; + } + + @override + String toString() { + return (StringBuffer('AgentsCompanion(') + ..write('id: $id, ') + ..write('displayName: $displayName, ') + ..write('agentType: $agentType, ') + ..write('bridgeUrl: $bridgeUrl, ') + ..write('authToken: $authToken, ') + ..write('workingDirectory: $workingDirectory, ') + ..write('status: $status, ') + ..write('lastConnectedAt: $lastConnectedAt, ') + ..write('createdAt: $createdAt, ') + ..write('updatedAt: $updatedAt, ') + ..write('rowid: $rowid') + ..write(')')) + .toString(); + } +} + +class $ApprovalsTable extends Approvals + with TableInfo<$ApprovalsTable, Approval> { + @override + final GeneratedDatabase attachedDatabase; + final String? _alias; + $ApprovalsTable(this.attachedDatabase, [this._alias]); + static const VerificationMeta _idMeta = const VerificationMeta('id'); + @override + late final GeneratedColumn id = GeneratedColumn( + 'id', aliasedName, false, + type: DriftSqlType.string, requiredDuringInsert: true); + static const VerificationMeta _sessionIdMeta = + const VerificationMeta('sessionId'); + @override + late final GeneratedColumn sessionId = GeneratedColumn( + 'session_id', aliasedName, false, + type: DriftSqlType.string, + requiredDuringInsert: true, + defaultConstraints: + GeneratedColumn.constraintIsAlways('REFERENCES sessions (id)')); + static const VerificationMeta _toolMeta = const VerificationMeta('tool'); + @override + late final GeneratedColumn tool = GeneratedColumn( + 'tool', aliasedName, false, + type: DriftSqlType.string, requiredDuringInsert: true); + static const VerificationMeta _descriptionMeta = + const VerificationMeta('description'); + @override + late final GeneratedColumn description = GeneratedColumn( + 'description', aliasedName, false, + type: DriftSqlType.string, requiredDuringInsert: true); + static const VerificationMeta _paramsMeta = const VerificationMeta('params'); + @override + late final GeneratedColumn params = GeneratedColumn( + 'params', aliasedName, false, + type: DriftSqlType.string, requiredDuringInsert: true); + static const VerificationMeta _reasoningMeta = + const VerificationMeta('reasoning'); + @override + late final GeneratedColumn reasoning = GeneratedColumn( + 'reasoning', aliasedName, true, + type: DriftSqlType.string, requiredDuringInsert: false); + static const VerificationMeta _riskLevelMeta = + const VerificationMeta('riskLevel'); + @override + late final GeneratedColumn riskLevel = GeneratedColumn( + 'risk_level', aliasedName, false, + type: DriftSqlType.string, requiredDuringInsert: true); + static const VerificationMeta _decisionMeta = + const VerificationMeta('decision'); + @override + late final GeneratedColumn decision = GeneratedColumn( + 'decision', aliasedName, false, + type: DriftSqlType.string, requiredDuringInsert: true); + static const VerificationMeta _modificationsMeta = + const VerificationMeta('modifications'); + @override + late final GeneratedColumn modifications = GeneratedColumn( + 'modifications', aliasedName, true, + type: DriftSqlType.string, requiredDuringInsert: false); + static const VerificationMeta _resultMeta = const VerificationMeta('result'); + @override + late final GeneratedColumn result = GeneratedColumn( + 'result', aliasedName, true, + type: DriftSqlType.string, requiredDuringInsert: false); + static const VerificationMeta _createdAtMeta = + const VerificationMeta('createdAt'); + @override + late final GeneratedColumn createdAt = GeneratedColumn( + 'created_at', aliasedName, false, + type: DriftSqlType.dateTime, requiredDuringInsert: true); + static const VerificationMeta _decidedAtMeta = + const VerificationMeta('decidedAt'); + @override + late final GeneratedColumn decidedAt = GeneratedColumn( + 'decided_at', aliasedName, true, + type: DriftSqlType.dateTime, requiredDuringInsert: false); + static const VerificationMeta _syncedMeta = const VerificationMeta('synced'); + @override + late final GeneratedColumn synced = GeneratedColumn( + 'synced', aliasedName, false, + type: DriftSqlType.bool, + requiredDuringInsert: false, + defaultConstraints: + GeneratedColumn.constraintIsAlways('CHECK ("synced" IN (0, 1))'), + defaultValue: const Constant(true)); + @override + List get $columns => [ + id, + sessionId, + tool, + description, + params, + reasoning, + riskLevel, + decision, + modifications, + result, + createdAt, + decidedAt, + synced + ]; + @override + String get aliasedName => _alias ?? actualTableName; + @override + String get actualTableName => $name; + static const String $name = 'approvals'; + @override + VerificationContext validateIntegrity(Insertable instance, + {bool isInserting = false}) { + final context = VerificationContext(); + final data = instance.toColumns(true); + if (data.containsKey('id')) { + context.handle(_idMeta, id.isAcceptableOrUnknown(data['id']!, _idMeta)); + } else if (isInserting) { + context.missing(_idMeta); + } + if (data.containsKey('session_id')) { + context.handle(_sessionIdMeta, + sessionId.isAcceptableOrUnknown(data['session_id']!, _sessionIdMeta)); + } else if (isInserting) { + context.missing(_sessionIdMeta); + } + if (data.containsKey('tool')) { + context.handle( + _toolMeta, tool.isAcceptableOrUnknown(data['tool']!, _toolMeta)); + } else if (isInserting) { + context.missing(_toolMeta); + } + if (data.containsKey('description')) { + context.handle( + _descriptionMeta, + description.isAcceptableOrUnknown( + data['description']!, _descriptionMeta)); + } else if (isInserting) { + context.missing(_descriptionMeta); + } + if (data.containsKey('params')) { + context.handle(_paramsMeta, + params.isAcceptableOrUnknown(data['params']!, _paramsMeta)); + } else if (isInserting) { + context.missing(_paramsMeta); + } + if (data.containsKey('reasoning')) { + context.handle(_reasoningMeta, + reasoning.isAcceptableOrUnknown(data['reasoning']!, _reasoningMeta)); + } + if (data.containsKey('risk_level')) { + context.handle(_riskLevelMeta, + riskLevel.isAcceptableOrUnknown(data['risk_level']!, _riskLevelMeta)); + } else if (isInserting) { + context.missing(_riskLevelMeta); + } + if (data.containsKey('decision')) { + context.handle(_decisionMeta, + decision.isAcceptableOrUnknown(data['decision']!, _decisionMeta)); + } else if (isInserting) { + context.missing(_decisionMeta); + } + if (data.containsKey('modifications')) { + context.handle( + _modificationsMeta, + modifications.isAcceptableOrUnknown( + data['modifications']!, _modificationsMeta)); + } + if (data.containsKey('result')) { + context.handle(_resultMeta, + result.isAcceptableOrUnknown(data['result']!, _resultMeta)); + } + if (data.containsKey('created_at')) { + context.handle(_createdAtMeta, + createdAt.isAcceptableOrUnknown(data['created_at']!, _createdAtMeta)); + } else if (isInserting) { + context.missing(_createdAtMeta); + } + if (data.containsKey('decided_at')) { + context.handle(_decidedAtMeta, + decidedAt.isAcceptableOrUnknown(data['decided_at']!, _decidedAtMeta)); + } + if (data.containsKey('synced')) { + context.handle(_syncedMeta, + synced.isAcceptableOrUnknown(data['synced']!, _syncedMeta)); + } + return context; + } + + @override + Set get $primaryKey => {id}; + @override + Approval map(Map data, {String? tablePrefix}) { + final effectivePrefix = tablePrefix != null ? '$tablePrefix.' : ''; + return Approval( + id: attachedDatabase.typeMapping + .read(DriftSqlType.string, data['${effectivePrefix}id'])!, + sessionId: attachedDatabase.typeMapping + .read(DriftSqlType.string, data['${effectivePrefix}session_id'])!, + tool: attachedDatabase.typeMapping + .read(DriftSqlType.string, data['${effectivePrefix}tool'])!, + description: attachedDatabase.typeMapping + .read(DriftSqlType.string, data['${effectivePrefix}description'])!, + params: attachedDatabase.typeMapping + .read(DriftSqlType.string, data['${effectivePrefix}params'])!, + reasoning: attachedDatabase.typeMapping + .read(DriftSqlType.string, data['${effectivePrefix}reasoning']), + riskLevel: attachedDatabase.typeMapping + .read(DriftSqlType.string, data['${effectivePrefix}risk_level'])!, + decision: attachedDatabase.typeMapping + .read(DriftSqlType.string, data['${effectivePrefix}decision'])!, + modifications: attachedDatabase.typeMapping + .read(DriftSqlType.string, data['${effectivePrefix}modifications']), + result: attachedDatabase.typeMapping + .read(DriftSqlType.string, data['${effectivePrefix}result']), + createdAt: attachedDatabase.typeMapping + .read(DriftSqlType.dateTime, data['${effectivePrefix}created_at'])!, + decidedAt: attachedDatabase.typeMapping + .read(DriftSqlType.dateTime, data['${effectivePrefix}decided_at']), + synced: attachedDatabase.typeMapping + .read(DriftSqlType.bool, data['${effectivePrefix}synced'])!, + ); + } + + @override + $ApprovalsTable createAlias(String alias) { + return $ApprovalsTable(attachedDatabase, alias); + } +} + +class Approval extends DataClass implements Insertable { + final String id; + final String sessionId; + final String tool; + final String description; + + /// JSON: tool parameters. + final String params; + + /// Agent's explanation. + final String? reasoning; + + /// "low" | "medium" | "high" | "critical" + final String riskLevel; + + /// "approved" | "rejected" | "modified" | "pending" + final String decision; + + /// User's modification instructions. + final String? modifications; + + /// JSON: tool execution result. + final String? result; + final DateTime createdAt; + final DateTime? decidedAt; + final bool synced; + const Approval( + {required this.id, + required this.sessionId, + required this.tool, + required this.description, + required this.params, + this.reasoning, + required this.riskLevel, + required this.decision, + this.modifications, + this.result, + required this.createdAt, + this.decidedAt, + required this.synced}); + @override + Map toColumns(bool nullToAbsent) { + final map = {}; + map['id'] = Variable(id); + map['session_id'] = Variable(sessionId); + map['tool'] = Variable(tool); + map['description'] = Variable(description); + map['params'] = Variable(params); + if (!nullToAbsent || reasoning != null) { + map['reasoning'] = Variable(reasoning); + } + map['risk_level'] = Variable(riskLevel); + map['decision'] = Variable(decision); + if (!nullToAbsent || modifications != null) { + map['modifications'] = Variable(modifications); + } + if (!nullToAbsent || result != null) { + map['result'] = Variable(result); + } + map['created_at'] = Variable(createdAt); + if (!nullToAbsent || decidedAt != null) { + map['decided_at'] = Variable(decidedAt); + } + map['synced'] = Variable(synced); + return map; + } + + ApprovalsCompanion toCompanion(bool nullToAbsent) { + return ApprovalsCompanion( + id: Value(id), + sessionId: Value(sessionId), + tool: Value(tool), + description: Value(description), + params: Value(params), + reasoning: reasoning == null && nullToAbsent + ? const Value.absent() + : Value(reasoning), + riskLevel: Value(riskLevel), + decision: Value(decision), + modifications: modifications == null && nullToAbsent + ? const Value.absent() + : Value(modifications), + result: + result == null && nullToAbsent ? const Value.absent() : Value(result), + createdAt: Value(createdAt), + decidedAt: decidedAt == null && nullToAbsent + ? const Value.absent() + : Value(decidedAt), + synced: Value(synced), + ); + } + + factory Approval.fromJson(Map json, + {ValueSerializer? serializer}) { + serializer ??= driftRuntimeOptions.defaultSerializer; + return Approval( + id: serializer.fromJson(json['id']), + sessionId: serializer.fromJson(json['sessionId']), + tool: serializer.fromJson(json['tool']), + description: serializer.fromJson(json['description']), + params: serializer.fromJson(json['params']), + reasoning: serializer.fromJson(json['reasoning']), + riskLevel: serializer.fromJson(json['riskLevel']), + decision: serializer.fromJson(json['decision']), + modifications: serializer.fromJson(json['modifications']), + result: serializer.fromJson(json['result']), + createdAt: serializer.fromJson(json['createdAt']), + decidedAt: serializer.fromJson(json['decidedAt']), + synced: serializer.fromJson(json['synced']), + ); + } + @override + Map toJson({ValueSerializer? serializer}) { + serializer ??= driftRuntimeOptions.defaultSerializer; + return { + 'id': serializer.toJson(id), + 'sessionId': serializer.toJson(sessionId), + 'tool': serializer.toJson(tool), + 'description': serializer.toJson(description), + 'params': serializer.toJson(params), + 'reasoning': serializer.toJson(reasoning), + 'riskLevel': serializer.toJson(riskLevel), + 'decision': serializer.toJson(decision), + 'modifications': serializer.toJson(modifications), + 'result': serializer.toJson(result), + 'createdAt': serializer.toJson(createdAt), + 'decidedAt': serializer.toJson(decidedAt), + 'synced': serializer.toJson(synced), + }; + } + + Approval copyWith( + {String? id, + String? sessionId, + String? tool, + String? description, + String? params, + Value reasoning = const Value.absent(), + String? riskLevel, + String? decision, + Value modifications = const Value.absent(), + Value result = const Value.absent(), + DateTime? createdAt, + Value decidedAt = const Value.absent(), + bool? synced}) => + Approval( + id: id ?? this.id, + sessionId: sessionId ?? this.sessionId, + tool: tool ?? this.tool, + description: description ?? this.description, + params: params ?? this.params, + reasoning: reasoning.present ? reasoning.value : this.reasoning, + riskLevel: riskLevel ?? this.riskLevel, + decision: decision ?? this.decision, + modifications: + modifications.present ? modifications.value : this.modifications, + result: result.present ? result.value : this.result, + createdAt: createdAt ?? this.createdAt, + decidedAt: decidedAt.present ? decidedAt.value : this.decidedAt, + synced: synced ?? this.synced, + ); + Approval copyWithCompanion(ApprovalsCompanion data) { + return Approval( + id: data.id.present ? data.id.value : this.id, + sessionId: data.sessionId.present ? data.sessionId.value : this.sessionId, + tool: data.tool.present ? data.tool.value : this.tool, + description: + data.description.present ? data.description.value : this.description, + params: data.params.present ? data.params.value : this.params, + reasoning: data.reasoning.present ? data.reasoning.value : this.reasoning, + riskLevel: data.riskLevel.present ? data.riskLevel.value : this.riskLevel, + decision: data.decision.present ? data.decision.value : this.decision, + modifications: data.modifications.present + ? data.modifications.value + : this.modifications, + result: data.result.present ? data.result.value : this.result, + createdAt: data.createdAt.present ? data.createdAt.value : this.createdAt, + decidedAt: data.decidedAt.present ? data.decidedAt.value : this.decidedAt, + synced: data.synced.present ? data.synced.value : this.synced, + ); + } + + @override + String toString() { + return (StringBuffer('Approval(') + ..write('id: $id, ') + ..write('sessionId: $sessionId, ') + ..write('tool: $tool, ') + ..write('description: $description, ') + ..write('params: $params, ') + ..write('reasoning: $reasoning, ') + ..write('riskLevel: $riskLevel, ') + ..write('decision: $decision, ') + ..write('modifications: $modifications, ') + ..write('result: $result, ') + ..write('createdAt: $createdAt, ') + ..write('decidedAt: $decidedAt, ') + ..write('synced: $synced') + ..write(')')) + .toString(); + } + + @override + int get hashCode => Object.hash( + id, + sessionId, + tool, + description, + params, + reasoning, + riskLevel, + decision, + modifications, + result, + createdAt, + decidedAt, + synced); + @override + bool operator ==(Object other) => + identical(this, other) || + (other is Approval && + other.id == this.id && + other.sessionId == this.sessionId && + other.tool == this.tool && + other.description == this.description && + other.params == this.params && + other.reasoning == this.reasoning && + other.riskLevel == this.riskLevel && + other.decision == this.decision && + other.modifications == this.modifications && + other.result == this.result && + other.createdAt == this.createdAt && + other.decidedAt == this.decidedAt && + other.synced == this.synced); +} + +class ApprovalsCompanion extends UpdateCompanion { + final Value id; + final Value sessionId; + final Value tool; + final Value description; + final Value params; + final Value reasoning; + final Value riskLevel; + final Value decision; + final Value modifications; + final Value result; + final Value createdAt; + final Value decidedAt; + final Value synced; + final Value rowid; + const ApprovalsCompanion({ + this.id = const Value.absent(), + this.sessionId = const Value.absent(), + this.tool = const Value.absent(), + this.description = const Value.absent(), + this.params = const Value.absent(), + this.reasoning = const Value.absent(), + this.riskLevel = const Value.absent(), + this.decision = const Value.absent(), + this.modifications = const Value.absent(), + this.result = const Value.absent(), + this.createdAt = const Value.absent(), + this.decidedAt = const Value.absent(), + this.synced = const Value.absent(), + this.rowid = const Value.absent(), + }); + ApprovalsCompanion.insert({ + required String id, + required String sessionId, + required String tool, + required String description, + required String params, + this.reasoning = const Value.absent(), + required String riskLevel, + required String decision, + this.modifications = const Value.absent(), + this.result = const Value.absent(), + required DateTime createdAt, + this.decidedAt = const Value.absent(), + this.synced = const Value.absent(), + this.rowid = const Value.absent(), + }) : id = Value(id), + sessionId = Value(sessionId), + tool = Value(tool), + description = Value(description), + params = Value(params), + riskLevel = Value(riskLevel), + decision = Value(decision), + createdAt = Value(createdAt); + static Insertable custom({ + Expression? id, + Expression? sessionId, + Expression? tool, + Expression? description, + Expression? params, + Expression? reasoning, + Expression? riskLevel, + Expression? decision, + Expression? modifications, + Expression? result, + Expression? createdAt, + Expression? decidedAt, + Expression? synced, + Expression? rowid, + }) { + return RawValuesInsertable({ + if (id != null) 'id': id, + if (sessionId != null) 'session_id': sessionId, + if (tool != null) 'tool': tool, + if (description != null) 'description': description, + if (params != null) 'params': params, + if (reasoning != null) 'reasoning': reasoning, + if (riskLevel != null) 'risk_level': riskLevel, + if (decision != null) 'decision': decision, + if (modifications != null) 'modifications': modifications, + if (result != null) 'result': result, + if (createdAt != null) 'created_at': createdAt, + if (decidedAt != null) 'decided_at': decidedAt, + if (synced != null) 'synced': synced, + if (rowid != null) 'rowid': rowid, + }); + } + + ApprovalsCompanion copyWith( + {Value? id, + Value? sessionId, + Value? tool, + Value? description, + Value? params, + Value? reasoning, + Value? riskLevel, + Value? decision, + Value? modifications, + Value? result, + Value? createdAt, + Value? decidedAt, + Value? synced, + Value? rowid}) { + return ApprovalsCompanion( + id: id ?? this.id, + sessionId: sessionId ?? this.sessionId, + tool: tool ?? this.tool, + description: description ?? this.description, + params: params ?? this.params, + reasoning: reasoning ?? this.reasoning, + riskLevel: riskLevel ?? this.riskLevel, + decision: decision ?? this.decision, + modifications: modifications ?? this.modifications, + result: result ?? this.result, + createdAt: createdAt ?? this.createdAt, + decidedAt: decidedAt ?? this.decidedAt, + synced: synced ?? this.synced, + rowid: rowid ?? this.rowid, + ); + } + + @override + Map toColumns(bool nullToAbsent) { + final map = {}; + if (id.present) { + map['id'] = Variable(id.value); + } + if (sessionId.present) { + map['session_id'] = Variable(sessionId.value); + } + if (tool.present) { + map['tool'] = Variable(tool.value); + } + if (description.present) { + map['description'] = Variable(description.value); + } + if (params.present) { + map['params'] = Variable(params.value); + } + if (reasoning.present) { + map['reasoning'] = Variable(reasoning.value); + } + if (riskLevel.present) { + map['risk_level'] = Variable(riskLevel.value); + } + if (decision.present) { + map['decision'] = Variable(decision.value); + } + if (modifications.present) { + map['modifications'] = Variable(modifications.value); + } + if (result.present) { + map['result'] = Variable(result.value); + } + if (createdAt.present) { + map['created_at'] = Variable(createdAt.value); + } + if (decidedAt.present) { + map['decided_at'] = Variable(decidedAt.value); + } + if (synced.present) { + map['synced'] = Variable(synced.value); + } + if (rowid.present) { + map['rowid'] = Variable(rowid.value); + } + return map; + } + + @override + String toString() { + return (StringBuffer('ApprovalsCompanion(') + ..write('id: $id, ') + ..write('sessionId: $sessionId, ') + ..write('tool: $tool, ') + ..write('description: $description, ') + ..write('params: $params, ') + ..write('reasoning: $reasoning, ') + ..write('riskLevel: $riskLevel, ') + ..write('decision: $decision, ') + ..write('modifications: $modifications, ') + ..write('result: $result, ') + ..write('createdAt: $createdAt, ') + ..write('decidedAt: $decidedAt, ') + ..write('synced: $synced, ') + ..write('rowid: $rowid') + ..write(')')) + .toString(); + } +} + +class $SyncQueueTable extends SyncQueue + with TableInfo<$SyncQueueTable, SyncQueueData> { + @override + final GeneratedDatabase attachedDatabase; + final String? _alias; + $SyncQueueTable(this.attachedDatabase, [this._alias]); + static const VerificationMeta _idMeta = const VerificationMeta('id'); + @override + late final GeneratedColumn id = GeneratedColumn( + 'id', aliasedName, false, + hasAutoIncrement: true, + type: DriftSqlType.int, + requiredDuringInsert: false, + defaultConstraints: + GeneratedColumn.constraintIsAlways('PRIMARY KEY AUTOINCREMENT')); + static const VerificationMeta _operationMeta = + const VerificationMeta('operation'); + @override + late final GeneratedColumn operation = GeneratedColumn( + 'operation', aliasedName, false, + type: DriftSqlType.string, requiredDuringInsert: true); + static const VerificationMeta _payloadMeta = + const VerificationMeta('payload'); + @override + late final GeneratedColumn payload = GeneratedColumn( + 'payload', aliasedName, false, + type: DriftSqlType.string, requiredDuringInsert: true); + static const VerificationMeta _sessionIdMeta = + const VerificationMeta('sessionId'); + @override + late final GeneratedColumn sessionId = GeneratedColumn( + 'session_id', aliasedName, true, + type: DriftSqlType.string, requiredDuringInsert: false); + static const VerificationMeta _createdAtMeta = + const VerificationMeta('createdAt'); + @override + late final GeneratedColumn createdAt = GeneratedColumn( + 'created_at', aliasedName, false, + type: DriftSqlType.dateTime, requiredDuringInsert: true); + static const VerificationMeta _syncedMeta = const VerificationMeta('synced'); + @override + late final GeneratedColumn synced = GeneratedColumn( + 'synced', aliasedName, false, + type: DriftSqlType.bool, + requiredDuringInsert: false, + defaultConstraints: + GeneratedColumn.constraintIsAlways('CHECK ("synced" IN (0, 1))'), + defaultValue: const Constant(false)); + static const VerificationMeta _retryCountMeta = + const VerificationMeta('retryCount'); + @override + late final GeneratedColumn retryCount = GeneratedColumn( + 'retry_count', aliasedName, false, + type: DriftSqlType.int, + requiredDuringInsert: false, + defaultValue: const Constant(0)); + static const VerificationMeta _lastErrorMeta = + const VerificationMeta('lastError'); + @override + late final GeneratedColumn lastError = GeneratedColumn( + 'last_error', aliasedName, true, + type: DriftSqlType.string, requiredDuringInsert: false); + @override + List get $columns => [ + id, + operation, + payload, + sessionId, + createdAt, + synced, + retryCount, + lastError + ]; + @override + String get aliasedName => _alias ?? actualTableName; + @override + String get actualTableName => $name; + static const String $name = 'sync_queue'; + @override + VerificationContext validateIntegrity(Insertable instance, + {bool isInserting = false}) { + final context = VerificationContext(); + final data = instance.toColumns(true); + if (data.containsKey('id')) { + context.handle(_idMeta, id.isAcceptableOrUnknown(data['id']!, _idMeta)); + } + if (data.containsKey('operation')) { + context.handle(_operationMeta, + operation.isAcceptableOrUnknown(data['operation']!, _operationMeta)); + } else if (isInserting) { + context.missing(_operationMeta); + } + if (data.containsKey('payload')) { + context.handle(_payloadMeta, + payload.isAcceptableOrUnknown(data['payload']!, _payloadMeta)); + } else if (isInserting) { + context.missing(_payloadMeta); + } + if (data.containsKey('session_id')) { + context.handle(_sessionIdMeta, + sessionId.isAcceptableOrUnknown(data['session_id']!, _sessionIdMeta)); + } + if (data.containsKey('created_at')) { + context.handle(_createdAtMeta, + createdAt.isAcceptableOrUnknown(data['created_at']!, _createdAtMeta)); + } else if (isInserting) { + context.missing(_createdAtMeta); + } + if (data.containsKey('synced')) { + context.handle(_syncedMeta, + synced.isAcceptableOrUnknown(data['synced']!, _syncedMeta)); + } + if (data.containsKey('retry_count')) { + context.handle( + _retryCountMeta, + retryCount.isAcceptableOrUnknown( + data['retry_count']!, _retryCountMeta)); + } + if (data.containsKey('last_error')) { + context.handle(_lastErrorMeta, + lastError.isAcceptableOrUnknown(data['last_error']!, _lastErrorMeta)); + } + return context; + } + + @override + Set get $primaryKey => {id}; + @override + SyncQueueData map(Map data, {String? tablePrefix}) { + final effectivePrefix = tablePrefix != null ? '$tablePrefix.' : ''; + return SyncQueueData( + id: attachedDatabase.typeMapping + .read(DriftSqlType.int, data['${effectivePrefix}id'])!, + operation: attachedDatabase.typeMapping + .read(DriftSqlType.string, data['${effectivePrefix}operation'])!, + payload: attachedDatabase.typeMapping + .read(DriftSqlType.string, data['${effectivePrefix}payload'])!, + sessionId: attachedDatabase.typeMapping + .read(DriftSqlType.string, data['${effectivePrefix}session_id']), + createdAt: attachedDatabase.typeMapping + .read(DriftSqlType.dateTime, data['${effectivePrefix}created_at'])!, + synced: attachedDatabase.typeMapping + .read(DriftSqlType.bool, data['${effectivePrefix}synced'])!, + retryCount: attachedDatabase.typeMapping + .read(DriftSqlType.int, data['${effectivePrefix}retry_count'])!, + lastError: attachedDatabase.typeMapping + .read(DriftSqlType.string, data['${effectivePrefix}last_error']), + ); + } + + @override + $SyncQueueTable createAlias(String alias) { + return $SyncQueueTable(attachedDatabase, alias); + } +} + +class SyncQueueData extends DataClass implements Insertable { + final int id; + + /// "send_message" | "approve_tool" | "git_command" + final String operation; + + /// JSON: full operation payload. + final String payload; + final String? sessionId; + final DateTime createdAt; + final bool synced; + final int retryCount; + final String? lastError; + const SyncQueueData( + {required this.id, + required this.operation, + required this.payload, + this.sessionId, + required this.createdAt, + required this.synced, + required this.retryCount, + this.lastError}); + @override + Map toColumns(bool nullToAbsent) { + final map = {}; + map['id'] = Variable(id); + map['operation'] = Variable(operation); + map['payload'] = Variable(payload); + if (!nullToAbsent || sessionId != null) { + map['session_id'] = Variable(sessionId); + } + map['created_at'] = Variable(createdAt); + map['synced'] = Variable(synced); + map['retry_count'] = Variable(retryCount); + if (!nullToAbsent || lastError != null) { + map['last_error'] = Variable(lastError); + } + return map; + } + + SyncQueueCompanion toCompanion(bool nullToAbsent) { + return SyncQueueCompanion( + id: Value(id), + operation: Value(operation), + payload: Value(payload), + sessionId: sessionId == null && nullToAbsent + ? const Value.absent() + : Value(sessionId), + createdAt: Value(createdAt), + synced: Value(synced), + retryCount: Value(retryCount), + lastError: lastError == null && nullToAbsent + ? const Value.absent() + : Value(lastError), + ); + } + + factory SyncQueueData.fromJson(Map json, + {ValueSerializer? serializer}) { + serializer ??= driftRuntimeOptions.defaultSerializer; + return SyncQueueData( + id: serializer.fromJson(json['id']), + operation: serializer.fromJson(json['operation']), + payload: serializer.fromJson(json['payload']), + sessionId: serializer.fromJson(json['sessionId']), + createdAt: serializer.fromJson(json['createdAt']), + synced: serializer.fromJson(json['synced']), + retryCount: serializer.fromJson(json['retryCount']), + lastError: serializer.fromJson(json['lastError']), + ); + } + @override + Map toJson({ValueSerializer? serializer}) { + serializer ??= driftRuntimeOptions.defaultSerializer; + return { + 'id': serializer.toJson(id), + 'operation': serializer.toJson(operation), + 'payload': serializer.toJson(payload), + 'sessionId': serializer.toJson(sessionId), + 'createdAt': serializer.toJson(createdAt), + 'synced': serializer.toJson(synced), + 'retryCount': serializer.toJson(retryCount), + 'lastError': serializer.toJson(lastError), + }; + } + + SyncQueueData copyWith( + {int? id, + String? operation, + String? payload, + Value sessionId = const Value.absent(), + DateTime? createdAt, + bool? synced, + int? retryCount, + Value lastError = const Value.absent()}) => + SyncQueueData( + id: id ?? this.id, + operation: operation ?? this.operation, + payload: payload ?? this.payload, + sessionId: sessionId.present ? sessionId.value : this.sessionId, + createdAt: createdAt ?? this.createdAt, + synced: synced ?? this.synced, + retryCount: retryCount ?? this.retryCount, + lastError: lastError.present ? lastError.value : this.lastError, + ); + SyncQueueData copyWithCompanion(SyncQueueCompanion data) { + return SyncQueueData( + id: data.id.present ? data.id.value : this.id, + operation: data.operation.present ? data.operation.value : this.operation, + payload: data.payload.present ? data.payload.value : this.payload, + sessionId: data.sessionId.present ? data.sessionId.value : this.sessionId, + createdAt: data.createdAt.present ? data.createdAt.value : this.createdAt, + synced: data.synced.present ? data.synced.value : this.synced, + retryCount: + data.retryCount.present ? data.retryCount.value : this.retryCount, + lastError: data.lastError.present ? data.lastError.value : this.lastError, + ); + } + + @override + String toString() { + return (StringBuffer('SyncQueueData(') + ..write('id: $id, ') + ..write('operation: $operation, ') + ..write('payload: $payload, ') + ..write('sessionId: $sessionId, ') + ..write('createdAt: $createdAt, ') + ..write('synced: $synced, ') + ..write('retryCount: $retryCount, ') + ..write('lastError: $lastError') + ..write(')')) + .toString(); + } + + @override + int get hashCode => Object.hash(id, operation, payload, sessionId, createdAt, + synced, retryCount, lastError); + @override + bool operator ==(Object other) => + identical(this, other) || + (other is SyncQueueData && + other.id == this.id && + other.operation == this.operation && + other.payload == this.payload && + other.sessionId == this.sessionId && + other.createdAt == this.createdAt && + other.synced == this.synced && + other.retryCount == this.retryCount && + other.lastError == this.lastError); +} + +class SyncQueueCompanion extends UpdateCompanion { + final Value id; + final Value operation; + final Value payload; + final Value sessionId; + final Value createdAt; + final Value synced; + final Value retryCount; + final Value lastError; + const SyncQueueCompanion({ + this.id = const Value.absent(), + this.operation = const Value.absent(), + this.payload = const Value.absent(), + this.sessionId = const Value.absent(), + this.createdAt = const Value.absent(), + this.synced = const Value.absent(), + this.retryCount = const Value.absent(), + this.lastError = const Value.absent(), + }); + SyncQueueCompanion.insert({ + this.id = const Value.absent(), + required String operation, + required String payload, + this.sessionId = const Value.absent(), + required DateTime createdAt, + this.synced = const Value.absent(), + this.retryCount = const Value.absent(), + this.lastError = const Value.absent(), + }) : operation = Value(operation), + payload = Value(payload), + createdAt = Value(createdAt); + static Insertable custom({ + Expression? id, + Expression? operation, + Expression? payload, + Expression? sessionId, + Expression? createdAt, + Expression? synced, + Expression? retryCount, + Expression? lastError, + }) { + return RawValuesInsertable({ + if (id != null) 'id': id, + if (operation != null) 'operation': operation, + if (payload != null) 'payload': payload, + if (sessionId != null) 'session_id': sessionId, + if (createdAt != null) 'created_at': createdAt, + if (synced != null) 'synced': synced, + if (retryCount != null) 'retry_count': retryCount, + if (lastError != null) 'last_error': lastError, + }); + } + + SyncQueueCompanion copyWith( + {Value? id, + Value? operation, + Value? payload, + Value? sessionId, + Value? createdAt, + Value? synced, + Value? retryCount, + Value? lastError}) { + return SyncQueueCompanion( + id: id ?? this.id, + operation: operation ?? this.operation, + payload: payload ?? this.payload, + sessionId: sessionId ?? this.sessionId, + createdAt: createdAt ?? this.createdAt, + synced: synced ?? this.synced, + retryCount: retryCount ?? this.retryCount, + lastError: lastError ?? this.lastError, + ); + } + + @override + Map toColumns(bool nullToAbsent) { + final map = {}; + if (id.present) { + map['id'] = Variable(id.value); + } + if (operation.present) { + map['operation'] = Variable(operation.value); + } + if (payload.present) { + map['payload'] = Variable(payload.value); + } + if (sessionId.present) { + map['session_id'] = Variable(sessionId.value); + } + if (createdAt.present) { + map['created_at'] = Variable(createdAt.value); + } + if (synced.present) { + map['synced'] = Variable(synced.value); + } + if (retryCount.present) { + map['retry_count'] = Variable(retryCount.value); + } + if (lastError.present) { + map['last_error'] = Variable(lastError.value); + } + return map; + } + + @override + String toString() { + return (StringBuffer('SyncQueueCompanion(') + ..write('id: $id, ') + ..write('operation: $operation, ') + ..write('payload: $payload, ') + ..write('sessionId: $sessionId, ') + ..write('createdAt: $createdAt, ') + ..write('synced: $synced, ') + ..write('retryCount: $retryCount, ') + ..write('lastError: $lastError') + ..write(')')) + .toString(); + } +} + +abstract class _$AppDatabase extends GeneratedDatabase { + _$AppDatabase(QueryExecutor e) : super(e); + $AppDatabaseManager get managers => $AppDatabaseManager(this); + late final $SessionsTable sessions = $SessionsTable(this); + late final $MessagesTable messages = $MessagesTable(this); + late final $AgentsTable agents = $AgentsTable(this); + late final $ApprovalsTable approvals = $ApprovalsTable(this); + late final $SyncQueueTable syncQueue = $SyncQueueTable(this); + late final SessionDao sessionDao = SessionDao(this as AppDatabase); + late final MessageDao messageDao = MessageDao(this as AppDatabase); + late final SyncDao syncDao = SyncDao(this as AppDatabase); + @override + Iterable> get allTables => + allSchemaEntities.whereType>(); + @override + List get allSchemaEntities => + [sessions, messages, agents, approvals, syncQueue]; +} + +typedef $$SessionsTableCreateCompanionBuilder = SessionsCompanion Function({ + required String id, + required String agentType, + Value agentId, + Value title, + required String workingDirectory, + Value branch, + required String status, + required DateTime createdAt, + Value lastMessageAt, + required DateTime updatedAt, + Value synced, + Value rowid, +}); +typedef $$SessionsTableUpdateCompanionBuilder = SessionsCompanion Function({ + Value id, + Value agentType, + Value agentId, + Value title, + Value workingDirectory, + Value branch, + Value status, + Value createdAt, + Value lastMessageAt, + Value updatedAt, + Value synced, + Value rowid, +}); + +final class $$SessionsTableReferences + extends BaseReferences<_$AppDatabase, $SessionsTable, Session> { + $$SessionsTableReferences(super.$_db, super.$_table, super.$_typedResult); + + static MultiTypedResultKey<$MessagesTable, List> _messagesRefsTable( + _$AppDatabase db) => + MultiTypedResultKey.fromTable(db.messages, + aliasName: + $_aliasNameGenerator(db.sessions.id, db.messages.sessionId)); + + $$MessagesTableProcessedTableManager get messagesRefs { + final manager = $$MessagesTableTableManager($_db, $_db.messages) + .filter((f) => f.sessionId.id.sqlEquals($_itemColumn('id')!)); + + final cache = $_typedResult.readTableOrNull(_messagesRefsTable($_db)); + return ProcessedTableManager( + manager.$state.copyWith(prefetchedData: cache)); + } + + static MultiTypedResultKey<$ApprovalsTable, List> + _approvalsRefsTable(_$AppDatabase db) => + MultiTypedResultKey.fromTable(db.approvals, + aliasName: + $_aliasNameGenerator(db.sessions.id, db.approvals.sessionId)); + + $$ApprovalsTableProcessedTableManager get approvalsRefs { + final manager = $$ApprovalsTableTableManager($_db, $_db.approvals) + .filter((f) => f.sessionId.id.sqlEquals($_itemColumn('id')!)); + + final cache = $_typedResult.readTableOrNull(_approvalsRefsTable($_db)); + return ProcessedTableManager( + manager.$state.copyWith(prefetchedData: cache)); + } +} + +class $$SessionsTableFilterComposer + extends Composer<_$AppDatabase, $SessionsTable> { + $$SessionsTableFilterComposer({ + required super.$db, + required super.$table, + super.joinBuilder, + super.$addJoinBuilderToRootComposer, + super.$removeJoinBuilderFromRootComposer, + }); + ColumnFilters get id => $composableBuilder( + column: $table.id, builder: (column) => ColumnFilters(column)); + + ColumnFilters get agentType => $composableBuilder( + column: $table.agentType, builder: (column) => ColumnFilters(column)); + + ColumnFilters get agentId => $composableBuilder( + column: $table.agentId, builder: (column) => ColumnFilters(column)); + + ColumnFilters get title => $composableBuilder( + column: $table.title, builder: (column) => ColumnFilters(column)); + + ColumnFilters get workingDirectory => $composableBuilder( + column: $table.workingDirectory, + builder: (column) => ColumnFilters(column)); + + ColumnFilters get branch => $composableBuilder( + column: $table.branch, builder: (column) => ColumnFilters(column)); + + ColumnFilters get status => $composableBuilder( + column: $table.status, builder: (column) => ColumnFilters(column)); + + ColumnFilters get createdAt => $composableBuilder( + column: $table.createdAt, builder: (column) => ColumnFilters(column)); + + ColumnFilters get lastMessageAt => $composableBuilder( + column: $table.lastMessageAt, builder: (column) => ColumnFilters(column)); + + ColumnFilters get updatedAt => $composableBuilder( + column: $table.updatedAt, builder: (column) => ColumnFilters(column)); + + ColumnFilters get synced => $composableBuilder( + column: $table.synced, builder: (column) => ColumnFilters(column)); + + Expression messagesRefs( + Expression Function($$MessagesTableFilterComposer f) f) { + final $$MessagesTableFilterComposer composer = $composerBuilder( + composer: this, + getCurrentColumn: (t) => t.id, + referencedTable: $db.messages, + getReferencedColumn: (t) => t.sessionId, + builder: (joinBuilder, + {$addJoinBuilderToRootComposer, + $removeJoinBuilderFromRootComposer}) => + $$MessagesTableFilterComposer( + $db: $db, + $table: $db.messages, + $addJoinBuilderToRootComposer: $addJoinBuilderToRootComposer, + joinBuilder: joinBuilder, + $removeJoinBuilderFromRootComposer: + $removeJoinBuilderFromRootComposer, + )); + return f(composer); + } + + Expression approvalsRefs( + Expression Function($$ApprovalsTableFilterComposer f) f) { + final $$ApprovalsTableFilterComposer composer = $composerBuilder( + composer: this, + getCurrentColumn: (t) => t.id, + referencedTable: $db.approvals, + getReferencedColumn: (t) => t.sessionId, + builder: (joinBuilder, + {$addJoinBuilderToRootComposer, + $removeJoinBuilderFromRootComposer}) => + $$ApprovalsTableFilterComposer( + $db: $db, + $table: $db.approvals, + $addJoinBuilderToRootComposer: $addJoinBuilderToRootComposer, + joinBuilder: joinBuilder, + $removeJoinBuilderFromRootComposer: + $removeJoinBuilderFromRootComposer, + )); + return f(composer); + } +} + +class $$SessionsTableOrderingComposer + extends Composer<_$AppDatabase, $SessionsTable> { + $$SessionsTableOrderingComposer({ + required super.$db, + required super.$table, + super.joinBuilder, + super.$addJoinBuilderToRootComposer, + super.$removeJoinBuilderFromRootComposer, + }); + ColumnOrderings get id => $composableBuilder( + column: $table.id, builder: (column) => ColumnOrderings(column)); + + ColumnOrderings get agentType => $composableBuilder( + column: $table.agentType, builder: (column) => ColumnOrderings(column)); + + ColumnOrderings get agentId => $composableBuilder( + column: $table.agentId, builder: (column) => ColumnOrderings(column)); + + ColumnOrderings get title => $composableBuilder( + column: $table.title, builder: (column) => ColumnOrderings(column)); + + ColumnOrderings get workingDirectory => $composableBuilder( + column: $table.workingDirectory, + builder: (column) => ColumnOrderings(column)); + + ColumnOrderings get branch => $composableBuilder( + column: $table.branch, builder: (column) => ColumnOrderings(column)); + + ColumnOrderings get status => $composableBuilder( + column: $table.status, builder: (column) => ColumnOrderings(column)); + + ColumnOrderings get createdAt => $composableBuilder( + column: $table.createdAt, builder: (column) => ColumnOrderings(column)); + + ColumnOrderings get lastMessageAt => $composableBuilder( + column: $table.lastMessageAt, + builder: (column) => ColumnOrderings(column)); + + ColumnOrderings get updatedAt => $composableBuilder( + column: $table.updatedAt, builder: (column) => ColumnOrderings(column)); + + ColumnOrderings get synced => $composableBuilder( + column: $table.synced, builder: (column) => ColumnOrderings(column)); +} + +class $$SessionsTableAnnotationComposer + extends Composer<_$AppDatabase, $SessionsTable> { + $$SessionsTableAnnotationComposer({ + required super.$db, + required super.$table, + super.joinBuilder, + super.$addJoinBuilderToRootComposer, + super.$removeJoinBuilderFromRootComposer, + }); + GeneratedColumn get id => + $composableBuilder(column: $table.id, builder: (column) => column); + + GeneratedColumn get agentType => + $composableBuilder(column: $table.agentType, builder: (column) => column); + + GeneratedColumn get agentId => + $composableBuilder(column: $table.agentId, builder: (column) => column); + + GeneratedColumn get title => + $composableBuilder(column: $table.title, builder: (column) => column); + + GeneratedColumn get workingDirectory => $composableBuilder( + column: $table.workingDirectory, builder: (column) => column); + + GeneratedColumn get branch => + $composableBuilder(column: $table.branch, builder: (column) => column); + + GeneratedColumn get status => + $composableBuilder(column: $table.status, builder: (column) => column); + + GeneratedColumn get createdAt => + $composableBuilder(column: $table.createdAt, builder: (column) => column); + + GeneratedColumn get lastMessageAt => $composableBuilder( + column: $table.lastMessageAt, builder: (column) => column); + + GeneratedColumn get updatedAt => + $composableBuilder(column: $table.updatedAt, builder: (column) => column); + + GeneratedColumn get synced => + $composableBuilder(column: $table.synced, builder: (column) => column); + + Expression messagesRefs( + Expression Function($$MessagesTableAnnotationComposer a) f) { + final $$MessagesTableAnnotationComposer composer = $composerBuilder( + composer: this, + getCurrentColumn: (t) => t.id, + referencedTable: $db.messages, + getReferencedColumn: (t) => t.sessionId, + builder: (joinBuilder, + {$addJoinBuilderToRootComposer, + $removeJoinBuilderFromRootComposer}) => + $$MessagesTableAnnotationComposer( + $db: $db, + $table: $db.messages, + $addJoinBuilderToRootComposer: $addJoinBuilderToRootComposer, + joinBuilder: joinBuilder, + $removeJoinBuilderFromRootComposer: + $removeJoinBuilderFromRootComposer, + )); + return f(composer); + } + + Expression approvalsRefs( + Expression Function($$ApprovalsTableAnnotationComposer a) f) { + final $$ApprovalsTableAnnotationComposer composer = $composerBuilder( + composer: this, + getCurrentColumn: (t) => t.id, + referencedTable: $db.approvals, + getReferencedColumn: (t) => t.sessionId, + builder: (joinBuilder, + {$addJoinBuilderToRootComposer, + $removeJoinBuilderFromRootComposer}) => + $$ApprovalsTableAnnotationComposer( + $db: $db, + $table: $db.approvals, + $addJoinBuilderToRootComposer: $addJoinBuilderToRootComposer, + joinBuilder: joinBuilder, + $removeJoinBuilderFromRootComposer: + $removeJoinBuilderFromRootComposer, + )); + return f(composer); + } +} + +class $$SessionsTableTableManager extends RootTableManager< + _$AppDatabase, + $SessionsTable, + Session, + $$SessionsTableFilterComposer, + $$SessionsTableOrderingComposer, + $$SessionsTableAnnotationComposer, + $$SessionsTableCreateCompanionBuilder, + $$SessionsTableUpdateCompanionBuilder, + (Session, $$SessionsTableReferences), + Session, + PrefetchHooks Function({bool messagesRefs, bool approvalsRefs})> { + $$SessionsTableTableManager(_$AppDatabase db, $SessionsTable table) + : super(TableManagerState( + db: db, + table: table, + createFilteringComposer: () => + $$SessionsTableFilterComposer($db: db, $table: table), + createOrderingComposer: () => + $$SessionsTableOrderingComposer($db: db, $table: table), + createComputedFieldComposer: () => + $$SessionsTableAnnotationComposer($db: db, $table: table), + updateCompanionCallback: ({ + Value id = const Value.absent(), + Value agentType = const Value.absent(), + Value agentId = const Value.absent(), + Value title = const Value.absent(), + Value workingDirectory = const Value.absent(), + Value branch = const Value.absent(), + Value status = const Value.absent(), + Value createdAt = const Value.absent(), + Value lastMessageAt = const Value.absent(), + Value updatedAt = const Value.absent(), + Value synced = const Value.absent(), + Value rowid = const Value.absent(), + }) => + SessionsCompanion( + id: id, + agentType: agentType, + agentId: agentId, + title: title, + workingDirectory: workingDirectory, + branch: branch, + status: status, + createdAt: createdAt, + lastMessageAt: lastMessageAt, + updatedAt: updatedAt, + synced: synced, + rowid: rowid, + ), + createCompanionCallback: ({ + required String id, + required String agentType, + Value agentId = const Value.absent(), + Value title = const Value.absent(), + required String workingDirectory, + Value branch = const Value.absent(), + required String status, + required DateTime createdAt, + Value lastMessageAt = const Value.absent(), + required DateTime updatedAt, + Value synced = const Value.absent(), + Value rowid = const Value.absent(), + }) => + SessionsCompanion.insert( + id: id, + agentType: agentType, + agentId: agentId, + title: title, + workingDirectory: workingDirectory, + branch: branch, + status: status, + createdAt: createdAt, + lastMessageAt: lastMessageAt, + updatedAt: updatedAt, + synced: synced, + rowid: rowid, + ), + withReferenceMapper: (p0) => p0 + .map((e) => + (e.readTable(table), $$SessionsTableReferences(db, table, e))) + .toList(), + prefetchHooksCallback: ( + {messagesRefs = false, approvalsRefs = false}) { + return PrefetchHooks( + db: db, + explicitlyWatchedTables: [ + if (messagesRefs) db.messages, + if (approvalsRefs) db.approvals + ], + addJoins: null, + getPrefetchedDataCallback: (items) async { + return [ + if (messagesRefs) + await $_getPrefetchedData( + currentTable: table, + referencedTable: + $$SessionsTableReferences._messagesRefsTable(db), + managerFromTypedResult: (p0) => + $$SessionsTableReferences(db, table, p0) + .messagesRefs, + referencedItemsForCurrentItem: + (item, referencedItems) => referencedItems + .where((e) => e.sessionId == item.id), + typedResults: items), + if (approvalsRefs) + await $_getPrefetchedData( + currentTable: table, + referencedTable: + $$SessionsTableReferences._approvalsRefsTable(db), + managerFromTypedResult: (p0) => + $$SessionsTableReferences(db, table, p0) + .approvalsRefs, + referencedItemsForCurrentItem: + (item, referencedItems) => referencedItems + .where((e) => e.sessionId == item.id), + typedResults: items) + ]; + }, + ); + }, + )); +} + +typedef $$SessionsTableProcessedTableManager = ProcessedTableManager< + _$AppDatabase, + $SessionsTable, + Session, + $$SessionsTableFilterComposer, + $$SessionsTableOrderingComposer, + $$SessionsTableAnnotationComposer, + $$SessionsTableCreateCompanionBuilder, + $$SessionsTableUpdateCompanionBuilder, + (Session, $$SessionsTableReferences), + Session, + PrefetchHooks Function({bool messagesRefs, bool approvalsRefs})>; +typedef $$MessagesTableCreateCompanionBuilder = MessagesCompanion Function({ + required String id, + required String sessionId, + required String role, + required String content, + Value messageType, + Value metadata, + required DateTime createdAt, + required DateTime updatedAt, + Value synced, + Value rowid, +}); +typedef $$MessagesTableUpdateCompanionBuilder = MessagesCompanion Function({ + Value id, + Value sessionId, + Value role, + Value content, + Value messageType, + Value metadata, + Value createdAt, + Value updatedAt, + Value synced, + Value rowid, +}); + +final class $$MessagesTableReferences + extends BaseReferences<_$AppDatabase, $MessagesTable, Message> { + $$MessagesTableReferences(super.$_db, super.$_table, super.$_typedResult); + + static $SessionsTable _sessionIdTable(_$AppDatabase db) => db.sessions + .createAlias($_aliasNameGenerator(db.messages.sessionId, db.sessions.id)); + + $$SessionsTableProcessedTableManager get sessionId { + final $_column = $_itemColumn('session_id')!; + + final manager = $$SessionsTableTableManager($_db, $_db.sessions) + .filter((f) => f.id.sqlEquals($_column)); + final item = $_typedResult.readTableOrNull(_sessionIdTable($_db)); + if (item == null) return manager; + return ProcessedTableManager( + manager.$state.copyWith(prefetchedData: [item])); + } +} + +class $$MessagesTableFilterComposer + extends Composer<_$AppDatabase, $MessagesTable> { + $$MessagesTableFilterComposer({ + required super.$db, + required super.$table, + super.joinBuilder, + super.$addJoinBuilderToRootComposer, + super.$removeJoinBuilderFromRootComposer, + }); + ColumnFilters get id => $composableBuilder( + column: $table.id, builder: (column) => ColumnFilters(column)); + + ColumnFilters get role => $composableBuilder( + column: $table.role, builder: (column) => ColumnFilters(column)); + + ColumnFilters get content => $composableBuilder( + column: $table.content, builder: (column) => ColumnFilters(column)); + + ColumnFilters get messageType => $composableBuilder( + column: $table.messageType, builder: (column) => ColumnFilters(column)); + + ColumnFilters get metadata => $composableBuilder( + column: $table.metadata, builder: (column) => ColumnFilters(column)); + + ColumnFilters get createdAt => $composableBuilder( + column: $table.createdAt, builder: (column) => ColumnFilters(column)); + + ColumnFilters get updatedAt => $composableBuilder( + column: $table.updatedAt, builder: (column) => ColumnFilters(column)); + + ColumnFilters get synced => $composableBuilder( + column: $table.synced, builder: (column) => ColumnFilters(column)); + + $$SessionsTableFilterComposer get sessionId { + final $$SessionsTableFilterComposer composer = $composerBuilder( + composer: this, + getCurrentColumn: (t) => t.sessionId, + referencedTable: $db.sessions, + getReferencedColumn: (t) => t.id, + builder: (joinBuilder, + {$addJoinBuilderToRootComposer, + $removeJoinBuilderFromRootComposer}) => + $$SessionsTableFilterComposer( + $db: $db, + $table: $db.sessions, + $addJoinBuilderToRootComposer: $addJoinBuilderToRootComposer, + joinBuilder: joinBuilder, + $removeJoinBuilderFromRootComposer: + $removeJoinBuilderFromRootComposer, + )); + return composer; + } +} + +class $$MessagesTableOrderingComposer + extends Composer<_$AppDatabase, $MessagesTable> { + $$MessagesTableOrderingComposer({ + required super.$db, + required super.$table, + super.joinBuilder, + super.$addJoinBuilderToRootComposer, + super.$removeJoinBuilderFromRootComposer, + }); + ColumnOrderings get id => $composableBuilder( + column: $table.id, builder: (column) => ColumnOrderings(column)); + + ColumnOrderings get role => $composableBuilder( + column: $table.role, builder: (column) => ColumnOrderings(column)); + + ColumnOrderings get content => $composableBuilder( + column: $table.content, builder: (column) => ColumnOrderings(column)); + + ColumnOrderings get messageType => $composableBuilder( + column: $table.messageType, builder: (column) => ColumnOrderings(column)); + + ColumnOrderings get metadata => $composableBuilder( + column: $table.metadata, builder: (column) => ColumnOrderings(column)); + + ColumnOrderings get createdAt => $composableBuilder( + column: $table.createdAt, builder: (column) => ColumnOrderings(column)); + + ColumnOrderings get updatedAt => $composableBuilder( + column: $table.updatedAt, builder: (column) => ColumnOrderings(column)); + + ColumnOrderings get synced => $composableBuilder( + column: $table.synced, builder: (column) => ColumnOrderings(column)); + + $$SessionsTableOrderingComposer get sessionId { + final $$SessionsTableOrderingComposer composer = $composerBuilder( + composer: this, + getCurrentColumn: (t) => t.sessionId, + referencedTable: $db.sessions, + getReferencedColumn: (t) => t.id, + builder: (joinBuilder, + {$addJoinBuilderToRootComposer, + $removeJoinBuilderFromRootComposer}) => + $$SessionsTableOrderingComposer( + $db: $db, + $table: $db.sessions, + $addJoinBuilderToRootComposer: $addJoinBuilderToRootComposer, + joinBuilder: joinBuilder, + $removeJoinBuilderFromRootComposer: + $removeJoinBuilderFromRootComposer, + )); + return composer; + } +} + +class $$MessagesTableAnnotationComposer + extends Composer<_$AppDatabase, $MessagesTable> { + $$MessagesTableAnnotationComposer({ + required super.$db, + required super.$table, + super.joinBuilder, + super.$addJoinBuilderToRootComposer, + super.$removeJoinBuilderFromRootComposer, + }); + GeneratedColumn get id => + $composableBuilder(column: $table.id, builder: (column) => column); + + GeneratedColumn get role => + $composableBuilder(column: $table.role, builder: (column) => column); + + GeneratedColumn get content => + $composableBuilder(column: $table.content, builder: (column) => column); + + GeneratedColumn get messageType => $composableBuilder( + column: $table.messageType, builder: (column) => column); + + GeneratedColumn get metadata => + $composableBuilder(column: $table.metadata, builder: (column) => column); + + GeneratedColumn get createdAt => + $composableBuilder(column: $table.createdAt, builder: (column) => column); + + GeneratedColumn get updatedAt => + $composableBuilder(column: $table.updatedAt, builder: (column) => column); + + GeneratedColumn get synced => + $composableBuilder(column: $table.synced, builder: (column) => column); + + $$SessionsTableAnnotationComposer get sessionId { + final $$SessionsTableAnnotationComposer composer = $composerBuilder( + composer: this, + getCurrentColumn: (t) => t.sessionId, + referencedTable: $db.sessions, + getReferencedColumn: (t) => t.id, + builder: (joinBuilder, + {$addJoinBuilderToRootComposer, + $removeJoinBuilderFromRootComposer}) => + $$SessionsTableAnnotationComposer( + $db: $db, + $table: $db.sessions, + $addJoinBuilderToRootComposer: $addJoinBuilderToRootComposer, + joinBuilder: joinBuilder, + $removeJoinBuilderFromRootComposer: + $removeJoinBuilderFromRootComposer, + )); + return composer; + } +} + +class $$MessagesTableTableManager extends RootTableManager< + _$AppDatabase, + $MessagesTable, + Message, + $$MessagesTableFilterComposer, + $$MessagesTableOrderingComposer, + $$MessagesTableAnnotationComposer, + $$MessagesTableCreateCompanionBuilder, + $$MessagesTableUpdateCompanionBuilder, + (Message, $$MessagesTableReferences), + Message, + PrefetchHooks Function({bool sessionId})> { + $$MessagesTableTableManager(_$AppDatabase db, $MessagesTable table) + : super(TableManagerState( + db: db, + table: table, + createFilteringComposer: () => + $$MessagesTableFilterComposer($db: db, $table: table), + createOrderingComposer: () => + $$MessagesTableOrderingComposer($db: db, $table: table), + createComputedFieldComposer: () => + $$MessagesTableAnnotationComposer($db: db, $table: table), + updateCompanionCallback: ({ + Value id = const Value.absent(), + Value sessionId = const Value.absent(), + Value role = const Value.absent(), + Value content = const Value.absent(), + Value messageType = const Value.absent(), + Value metadata = const Value.absent(), + Value createdAt = const Value.absent(), + Value updatedAt = const Value.absent(), + Value synced = const Value.absent(), + Value rowid = const Value.absent(), + }) => + MessagesCompanion( + id: id, + sessionId: sessionId, + role: role, + content: content, + messageType: messageType, + metadata: metadata, + createdAt: createdAt, + updatedAt: updatedAt, + synced: synced, + rowid: rowid, + ), + createCompanionCallback: ({ + required String id, + required String sessionId, + required String role, + required String content, + Value messageType = const Value.absent(), + Value metadata = const Value.absent(), + required DateTime createdAt, + required DateTime updatedAt, + Value synced = const Value.absent(), + Value rowid = const Value.absent(), + }) => + MessagesCompanion.insert( + id: id, + sessionId: sessionId, + role: role, + content: content, + messageType: messageType, + metadata: metadata, + createdAt: createdAt, + updatedAt: updatedAt, + synced: synced, + rowid: rowid, + ), + withReferenceMapper: (p0) => p0 + .map((e) => + (e.readTable(table), $$MessagesTableReferences(db, table, e))) + .toList(), + prefetchHooksCallback: ({sessionId = false}) { + return PrefetchHooks( + db: db, + explicitlyWatchedTables: [], + addJoins: < + T extends TableManagerState< + dynamic, + dynamic, + dynamic, + dynamic, + dynamic, + dynamic, + dynamic, + dynamic, + dynamic, + dynamic, + dynamic>>(state) { + if (sessionId) { + state = state.withJoin( + currentTable: table, + currentColumn: table.sessionId, + referencedTable: + $$MessagesTableReferences._sessionIdTable(db), + referencedColumn: + $$MessagesTableReferences._sessionIdTable(db).id, + ) as T; + } + + return state; + }, + getPrefetchedDataCallback: (items) async { + return []; + }, + ); + }, + )); +} + +typedef $$MessagesTableProcessedTableManager = ProcessedTableManager< + _$AppDatabase, + $MessagesTable, + Message, + $$MessagesTableFilterComposer, + $$MessagesTableOrderingComposer, + $$MessagesTableAnnotationComposer, + $$MessagesTableCreateCompanionBuilder, + $$MessagesTableUpdateCompanionBuilder, + (Message, $$MessagesTableReferences), + Message, + PrefetchHooks Function({bool sessionId})>; +typedef $$AgentsTableCreateCompanionBuilder = AgentsCompanion Function({ + required String id, + required String displayName, + required String agentType, + required String bridgeUrl, + required String authToken, + Value workingDirectory, + Value status, + Value lastConnectedAt, + required DateTime createdAt, + required DateTime updatedAt, + Value rowid, +}); +typedef $$AgentsTableUpdateCompanionBuilder = AgentsCompanion Function({ + Value id, + Value displayName, + Value agentType, + Value bridgeUrl, + Value authToken, + Value workingDirectory, + Value status, + Value lastConnectedAt, + Value createdAt, + Value updatedAt, + Value rowid, +}); + +class $$AgentsTableFilterComposer + extends Composer<_$AppDatabase, $AgentsTable> { + $$AgentsTableFilterComposer({ + required super.$db, + required super.$table, + super.joinBuilder, + super.$addJoinBuilderToRootComposer, + super.$removeJoinBuilderFromRootComposer, + }); + ColumnFilters get id => $composableBuilder( + column: $table.id, builder: (column) => ColumnFilters(column)); + + ColumnFilters get displayName => $composableBuilder( + column: $table.displayName, builder: (column) => ColumnFilters(column)); + + ColumnFilters get agentType => $composableBuilder( + column: $table.agentType, builder: (column) => ColumnFilters(column)); + + ColumnFilters get bridgeUrl => $composableBuilder( + column: $table.bridgeUrl, builder: (column) => ColumnFilters(column)); + + ColumnFilters get authToken => $composableBuilder( + column: $table.authToken, builder: (column) => ColumnFilters(column)); + + ColumnFilters get workingDirectory => $composableBuilder( + column: $table.workingDirectory, + builder: (column) => ColumnFilters(column)); + + ColumnFilters get status => $composableBuilder( + column: $table.status, builder: (column) => ColumnFilters(column)); + + ColumnFilters get lastConnectedAt => $composableBuilder( + column: $table.lastConnectedAt, + builder: (column) => ColumnFilters(column)); + + ColumnFilters get createdAt => $composableBuilder( + column: $table.createdAt, builder: (column) => ColumnFilters(column)); + + ColumnFilters get updatedAt => $composableBuilder( + column: $table.updatedAt, builder: (column) => ColumnFilters(column)); +} + +class $$AgentsTableOrderingComposer + extends Composer<_$AppDatabase, $AgentsTable> { + $$AgentsTableOrderingComposer({ + required super.$db, + required super.$table, + super.joinBuilder, + super.$addJoinBuilderToRootComposer, + super.$removeJoinBuilderFromRootComposer, + }); + ColumnOrderings get id => $composableBuilder( + column: $table.id, builder: (column) => ColumnOrderings(column)); + + ColumnOrderings get displayName => $composableBuilder( + column: $table.displayName, builder: (column) => ColumnOrderings(column)); + + ColumnOrderings get agentType => $composableBuilder( + column: $table.agentType, builder: (column) => ColumnOrderings(column)); + + ColumnOrderings get bridgeUrl => $composableBuilder( + column: $table.bridgeUrl, builder: (column) => ColumnOrderings(column)); + + ColumnOrderings get authToken => $composableBuilder( + column: $table.authToken, builder: (column) => ColumnOrderings(column)); + + ColumnOrderings get workingDirectory => $composableBuilder( + column: $table.workingDirectory, + builder: (column) => ColumnOrderings(column)); + + ColumnOrderings get status => $composableBuilder( + column: $table.status, builder: (column) => ColumnOrderings(column)); + + ColumnOrderings get lastConnectedAt => $composableBuilder( + column: $table.lastConnectedAt, + builder: (column) => ColumnOrderings(column)); + + ColumnOrderings get createdAt => $composableBuilder( + column: $table.createdAt, builder: (column) => ColumnOrderings(column)); + + ColumnOrderings get updatedAt => $composableBuilder( + column: $table.updatedAt, builder: (column) => ColumnOrderings(column)); +} + +class $$AgentsTableAnnotationComposer + extends Composer<_$AppDatabase, $AgentsTable> { + $$AgentsTableAnnotationComposer({ + required super.$db, + required super.$table, + super.joinBuilder, + super.$addJoinBuilderToRootComposer, + super.$removeJoinBuilderFromRootComposer, + }); + GeneratedColumn get id => + $composableBuilder(column: $table.id, builder: (column) => column); + + GeneratedColumn get displayName => $composableBuilder( + column: $table.displayName, builder: (column) => column); + + GeneratedColumn get agentType => + $composableBuilder(column: $table.agentType, builder: (column) => column); + + GeneratedColumn get bridgeUrl => + $composableBuilder(column: $table.bridgeUrl, builder: (column) => column); + + GeneratedColumn get authToken => + $composableBuilder(column: $table.authToken, builder: (column) => column); + + GeneratedColumn get workingDirectory => $composableBuilder( + column: $table.workingDirectory, builder: (column) => column); + + GeneratedColumn get status => + $composableBuilder(column: $table.status, builder: (column) => column); + + GeneratedColumn get lastConnectedAt => $composableBuilder( + column: $table.lastConnectedAt, builder: (column) => column); + + GeneratedColumn get createdAt => + $composableBuilder(column: $table.createdAt, builder: (column) => column); + + GeneratedColumn get updatedAt => + $composableBuilder(column: $table.updatedAt, builder: (column) => column); +} + +class $$AgentsTableTableManager extends RootTableManager< + _$AppDatabase, + $AgentsTable, + Agent, + $$AgentsTableFilterComposer, + $$AgentsTableOrderingComposer, + $$AgentsTableAnnotationComposer, + $$AgentsTableCreateCompanionBuilder, + $$AgentsTableUpdateCompanionBuilder, + (Agent, BaseReferences<_$AppDatabase, $AgentsTable, Agent>), + Agent, + PrefetchHooks Function()> { + $$AgentsTableTableManager(_$AppDatabase db, $AgentsTable table) + : super(TableManagerState( + db: db, + table: table, + createFilteringComposer: () => + $$AgentsTableFilterComposer($db: db, $table: table), + createOrderingComposer: () => + $$AgentsTableOrderingComposer($db: db, $table: table), + createComputedFieldComposer: () => + $$AgentsTableAnnotationComposer($db: db, $table: table), + updateCompanionCallback: ({ + Value id = const Value.absent(), + Value displayName = const Value.absent(), + Value agentType = const Value.absent(), + Value bridgeUrl = const Value.absent(), + Value authToken = const Value.absent(), + Value workingDirectory = const Value.absent(), + Value status = const Value.absent(), + Value lastConnectedAt = const Value.absent(), + Value createdAt = const Value.absent(), + Value updatedAt = const Value.absent(), + Value rowid = const Value.absent(), + }) => + AgentsCompanion( + id: id, + displayName: displayName, + agentType: agentType, + bridgeUrl: bridgeUrl, + authToken: authToken, + workingDirectory: workingDirectory, + status: status, + lastConnectedAt: lastConnectedAt, + createdAt: createdAt, + updatedAt: updatedAt, + rowid: rowid, + ), + createCompanionCallback: ({ + required String id, + required String displayName, + required String agentType, + required String bridgeUrl, + required String authToken, + Value workingDirectory = const Value.absent(), + Value status = const Value.absent(), + Value lastConnectedAt = const Value.absent(), + required DateTime createdAt, + required DateTime updatedAt, + Value rowid = const Value.absent(), + }) => + AgentsCompanion.insert( + id: id, + displayName: displayName, + agentType: agentType, + bridgeUrl: bridgeUrl, + authToken: authToken, + workingDirectory: workingDirectory, + status: status, + lastConnectedAt: lastConnectedAt, + createdAt: createdAt, + updatedAt: updatedAt, + rowid: rowid, + ), + withReferenceMapper: (p0) => p0 + .map((e) => (e.readTable(table), BaseReferences(db, table, e))) + .toList(), + prefetchHooksCallback: null, + )); +} + +typedef $$AgentsTableProcessedTableManager = ProcessedTableManager< + _$AppDatabase, + $AgentsTable, + Agent, + $$AgentsTableFilterComposer, + $$AgentsTableOrderingComposer, + $$AgentsTableAnnotationComposer, + $$AgentsTableCreateCompanionBuilder, + $$AgentsTableUpdateCompanionBuilder, + (Agent, BaseReferences<_$AppDatabase, $AgentsTable, Agent>), + Agent, + PrefetchHooks Function()>; +typedef $$ApprovalsTableCreateCompanionBuilder = ApprovalsCompanion Function({ + required String id, + required String sessionId, + required String tool, + required String description, + required String params, + Value reasoning, + required String riskLevel, + required String decision, + Value modifications, + Value result, + required DateTime createdAt, + Value decidedAt, + Value synced, + Value rowid, +}); +typedef $$ApprovalsTableUpdateCompanionBuilder = ApprovalsCompanion Function({ + Value id, + Value sessionId, + Value tool, + Value description, + Value params, + Value reasoning, + Value riskLevel, + Value decision, + Value modifications, + Value result, + Value createdAt, + Value decidedAt, + Value synced, + Value rowid, +}); + +final class $$ApprovalsTableReferences + extends BaseReferences<_$AppDatabase, $ApprovalsTable, Approval> { + $$ApprovalsTableReferences(super.$_db, super.$_table, super.$_typedResult); + + static $SessionsTable _sessionIdTable(_$AppDatabase db) => + db.sessions.createAlias( + $_aliasNameGenerator(db.approvals.sessionId, db.sessions.id)); + + $$SessionsTableProcessedTableManager get sessionId { + final $_column = $_itemColumn('session_id')!; + + final manager = $$SessionsTableTableManager($_db, $_db.sessions) + .filter((f) => f.id.sqlEquals($_column)); + final item = $_typedResult.readTableOrNull(_sessionIdTable($_db)); + if (item == null) return manager; + return ProcessedTableManager( + manager.$state.copyWith(prefetchedData: [item])); + } +} + +class $$ApprovalsTableFilterComposer + extends Composer<_$AppDatabase, $ApprovalsTable> { + $$ApprovalsTableFilterComposer({ + required super.$db, + required super.$table, + super.joinBuilder, + super.$addJoinBuilderToRootComposer, + super.$removeJoinBuilderFromRootComposer, + }); + ColumnFilters get id => $composableBuilder( + column: $table.id, builder: (column) => ColumnFilters(column)); + + ColumnFilters get tool => $composableBuilder( + column: $table.tool, builder: (column) => ColumnFilters(column)); + + ColumnFilters get description => $composableBuilder( + column: $table.description, builder: (column) => ColumnFilters(column)); + + ColumnFilters get params => $composableBuilder( + column: $table.params, builder: (column) => ColumnFilters(column)); + + ColumnFilters get reasoning => $composableBuilder( + column: $table.reasoning, builder: (column) => ColumnFilters(column)); + + ColumnFilters get riskLevel => $composableBuilder( + column: $table.riskLevel, builder: (column) => ColumnFilters(column)); + + ColumnFilters get decision => $composableBuilder( + column: $table.decision, builder: (column) => ColumnFilters(column)); + + ColumnFilters get modifications => $composableBuilder( + column: $table.modifications, builder: (column) => ColumnFilters(column)); + + ColumnFilters get result => $composableBuilder( + column: $table.result, builder: (column) => ColumnFilters(column)); + + ColumnFilters get createdAt => $composableBuilder( + column: $table.createdAt, builder: (column) => ColumnFilters(column)); + + ColumnFilters get decidedAt => $composableBuilder( + column: $table.decidedAt, builder: (column) => ColumnFilters(column)); + + ColumnFilters get synced => $composableBuilder( + column: $table.synced, builder: (column) => ColumnFilters(column)); + + $$SessionsTableFilterComposer get sessionId { + final $$SessionsTableFilterComposer composer = $composerBuilder( + composer: this, + getCurrentColumn: (t) => t.sessionId, + referencedTable: $db.sessions, + getReferencedColumn: (t) => t.id, + builder: (joinBuilder, + {$addJoinBuilderToRootComposer, + $removeJoinBuilderFromRootComposer}) => + $$SessionsTableFilterComposer( + $db: $db, + $table: $db.sessions, + $addJoinBuilderToRootComposer: $addJoinBuilderToRootComposer, + joinBuilder: joinBuilder, + $removeJoinBuilderFromRootComposer: + $removeJoinBuilderFromRootComposer, + )); + return composer; + } +} + +class $$ApprovalsTableOrderingComposer + extends Composer<_$AppDatabase, $ApprovalsTable> { + $$ApprovalsTableOrderingComposer({ + required super.$db, + required super.$table, + super.joinBuilder, + super.$addJoinBuilderToRootComposer, + super.$removeJoinBuilderFromRootComposer, + }); + ColumnOrderings get id => $composableBuilder( + column: $table.id, builder: (column) => ColumnOrderings(column)); + + ColumnOrderings get tool => $composableBuilder( + column: $table.tool, builder: (column) => ColumnOrderings(column)); + + ColumnOrderings get description => $composableBuilder( + column: $table.description, builder: (column) => ColumnOrderings(column)); + + ColumnOrderings get params => $composableBuilder( + column: $table.params, builder: (column) => ColumnOrderings(column)); + + ColumnOrderings get reasoning => $composableBuilder( + column: $table.reasoning, builder: (column) => ColumnOrderings(column)); + + ColumnOrderings get riskLevel => $composableBuilder( + column: $table.riskLevel, builder: (column) => ColumnOrderings(column)); + + ColumnOrderings get decision => $composableBuilder( + column: $table.decision, builder: (column) => ColumnOrderings(column)); + + ColumnOrderings get modifications => $composableBuilder( + column: $table.modifications, + builder: (column) => ColumnOrderings(column)); + + ColumnOrderings get result => $composableBuilder( + column: $table.result, builder: (column) => ColumnOrderings(column)); + + ColumnOrderings get createdAt => $composableBuilder( + column: $table.createdAt, builder: (column) => ColumnOrderings(column)); + + ColumnOrderings get decidedAt => $composableBuilder( + column: $table.decidedAt, builder: (column) => ColumnOrderings(column)); + + ColumnOrderings get synced => $composableBuilder( + column: $table.synced, builder: (column) => ColumnOrderings(column)); + + $$SessionsTableOrderingComposer get sessionId { + final $$SessionsTableOrderingComposer composer = $composerBuilder( + composer: this, + getCurrentColumn: (t) => t.sessionId, + referencedTable: $db.sessions, + getReferencedColumn: (t) => t.id, + builder: (joinBuilder, + {$addJoinBuilderToRootComposer, + $removeJoinBuilderFromRootComposer}) => + $$SessionsTableOrderingComposer( + $db: $db, + $table: $db.sessions, + $addJoinBuilderToRootComposer: $addJoinBuilderToRootComposer, + joinBuilder: joinBuilder, + $removeJoinBuilderFromRootComposer: + $removeJoinBuilderFromRootComposer, + )); + return composer; + } +} + +class $$ApprovalsTableAnnotationComposer + extends Composer<_$AppDatabase, $ApprovalsTable> { + $$ApprovalsTableAnnotationComposer({ + required super.$db, + required super.$table, + super.joinBuilder, + super.$addJoinBuilderToRootComposer, + super.$removeJoinBuilderFromRootComposer, + }); + GeneratedColumn get id => + $composableBuilder(column: $table.id, builder: (column) => column); + + GeneratedColumn get tool => + $composableBuilder(column: $table.tool, builder: (column) => column); + + GeneratedColumn get description => $composableBuilder( + column: $table.description, builder: (column) => column); + + GeneratedColumn get params => + $composableBuilder(column: $table.params, builder: (column) => column); + + GeneratedColumn get reasoning => + $composableBuilder(column: $table.reasoning, builder: (column) => column); + + GeneratedColumn get riskLevel => + $composableBuilder(column: $table.riskLevel, builder: (column) => column); + + GeneratedColumn get decision => + $composableBuilder(column: $table.decision, builder: (column) => column); + + GeneratedColumn get modifications => $composableBuilder( + column: $table.modifications, builder: (column) => column); + + GeneratedColumn get result => + $composableBuilder(column: $table.result, builder: (column) => column); + + GeneratedColumn get createdAt => + $composableBuilder(column: $table.createdAt, builder: (column) => column); + + GeneratedColumn get decidedAt => + $composableBuilder(column: $table.decidedAt, builder: (column) => column); + + GeneratedColumn get synced => + $composableBuilder(column: $table.synced, builder: (column) => column); + + $$SessionsTableAnnotationComposer get sessionId { + final $$SessionsTableAnnotationComposer composer = $composerBuilder( + composer: this, + getCurrentColumn: (t) => t.sessionId, + referencedTable: $db.sessions, + getReferencedColumn: (t) => t.id, + builder: (joinBuilder, + {$addJoinBuilderToRootComposer, + $removeJoinBuilderFromRootComposer}) => + $$SessionsTableAnnotationComposer( + $db: $db, + $table: $db.sessions, + $addJoinBuilderToRootComposer: $addJoinBuilderToRootComposer, + joinBuilder: joinBuilder, + $removeJoinBuilderFromRootComposer: + $removeJoinBuilderFromRootComposer, + )); + return composer; + } +} + +class $$ApprovalsTableTableManager extends RootTableManager< + _$AppDatabase, + $ApprovalsTable, + Approval, + $$ApprovalsTableFilterComposer, + $$ApprovalsTableOrderingComposer, + $$ApprovalsTableAnnotationComposer, + $$ApprovalsTableCreateCompanionBuilder, + $$ApprovalsTableUpdateCompanionBuilder, + (Approval, $$ApprovalsTableReferences), + Approval, + PrefetchHooks Function({bool sessionId})> { + $$ApprovalsTableTableManager(_$AppDatabase db, $ApprovalsTable table) + : super(TableManagerState( + db: db, + table: table, + createFilteringComposer: () => + $$ApprovalsTableFilterComposer($db: db, $table: table), + createOrderingComposer: () => + $$ApprovalsTableOrderingComposer($db: db, $table: table), + createComputedFieldComposer: () => + $$ApprovalsTableAnnotationComposer($db: db, $table: table), + updateCompanionCallback: ({ + Value id = const Value.absent(), + Value sessionId = const Value.absent(), + Value tool = const Value.absent(), + Value description = const Value.absent(), + Value params = const Value.absent(), + Value reasoning = const Value.absent(), + Value riskLevel = const Value.absent(), + Value decision = const Value.absent(), + Value modifications = const Value.absent(), + Value result = const Value.absent(), + Value createdAt = const Value.absent(), + Value decidedAt = const Value.absent(), + Value synced = const Value.absent(), + Value rowid = const Value.absent(), + }) => + ApprovalsCompanion( + id: id, + sessionId: sessionId, + tool: tool, + description: description, + params: params, + reasoning: reasoning, + riskLevel: riskLevel, + decision: decision, + modifications: modifications, + result: result, + createdAt: createdAt, + decidedAt: decidedAt, + synced: synced, + rowid: rowid, + ), + createCompanionCallback: ({ + required String id, + required String sessionId, + required String tool, + required String description, + required String params, + Value reasoning = const Value.absent(), + required String riskLevel, + required String decision, + Value modifications = const Value.absent(), + Value result = const Value.absent(), + required DateTime createdAt, + Value decidedAt = const Value.absent(), + Value synced = const Value.absent(), + Value rowid = const Value.absent(), + }) => + ApprovalsCompanion.insert( + id: id, + sessionId: sessionId, + tool: tool, + description: description, + params: params, + reasoning: reasoning, + riskLevel: riskLevel, + decision: decision, + modifications: modifications, + result: result, + createdAt: createdAt, + decidedAt: decidedAt, + synced: synced, + rowid: rowid, + ), + withReferenceMapper: (p0) => p0 + .map((e) => ( + e.readTable(table), + $$ApprovalsTableReferences(db, table, e) + )) + .toList(), + prefetchHooksCallback: ({sessionId = false}) { + return PrefetchHooks( + db: db, + explicitlyWatchedTables: [], + addJoins: < + T extends TableManagerState< + dynamic, + dynamic, + dynamic, + dynamic, + dynamic, + dynamic, + dynamic, + dynamic, + dynamic, + dynamic, + dynamic>>(state) { + if (sessionId) { + state = state.withJoin( + currentTable: table, + currentColumn: table.sessionId, + referencedTable: + $$ApprovalsTableReferences._sessionIdTable(db), + referencedColumn: + $$ApprovalsTableReferences._sessionIdTable(db).id, + ) as T; + } + + return state; + }, + getPrefetchedDataCallback: (items) async { + return []; + }, + ); + }, + )); +} + +typedef $$ApprovalsTableProcessedTableManager = ProcessedTableManager< + _$AppDatabase, + $ApprovalsTable, + Approval, + $$ApprovalsTableFilterComposer, + $$ApprovalsTableOrderingComposer, + $$ApprovalsTableAnnotationComposer, + $$ApprovalsTableCreateCompanionBuilder, + $$ApprovalsTableUpdateCompanionBuilder, + (Approval, $$ApprovalsTableReferences), + Approval, + PrefetchHooks Function({bool sessionId})>; +typedef $$SyncQueueTableCreateCompanionBuilder = SyncQueueCompanion Function({ + Value id, + required String operation, + required String payload, + Value sessionId, + required DateTime createdAt, + Value synced, + Value retryCount, + Value lastError, +}); +typedef $$SyncQueueTableUpdateCompanionBuilder = SyncQueueCompanion Function({ + Value id, + Value operation, + Value payload, + Value sessionId, + Value createdAt, + Value synced, + Value retryCount, + Value lastError, +}); + +class $$SyncQueueTableFilterComposer + extends Composer<_$AppDatabase, $SyncQueueTable> { + $$SyncQueueTableFilterComposer({ + required super.$db, + required super.$table, + super.joinBuilder, + super.$addJoinBuilderToRootComposer, + super.$removeJoinBuilderFromRootComposer, + }); + ColumnFilters get id => $composableBuilder( + column: $table.id, builder: (column) => ColumnFilters(column)); + + ColumnFilters get operation => $composableBuilder( + column: $table.operation, builder: (column) => ColumnFilters(column)); + + ColumnFilters get payload => $composableBuilder( + column: $table.payload, builder: (column) => ColumnFilters(column)); + + ColumnFilters get sessionId => $composableBuilder( + column: $table.sessionId, builder: (column) => ColumnFilters(column)); + + ColumnFilters get createdAt => $composableBuilder( + column: $table.createdAt, builder: (column) => ColumnFilters(column)); + + ColumnFilters get synced => $composableBuilder( + column: $table.synced, builder: (column) => ColumnFilters(column)); + + ColumnFilters get retryCount => $composableBuilder( + column: $table.retryCount, builder: (column) => ColumnFilters(column)); + + ColumnFilters get lastError => $composableBuilder( + column: $table.lastError, builder: (column) => ColumnFilters(column)); +} + +class $$SyncQueueTableOrderingComposer + extends Composer<_$AppDatabase, $SyncQueueTable> { + $$SyncQueueTableOrderingComposer({ + required super.$db, + required super.$table, + super.joinBuilder, + super.$addJoinBuilderToRootComposer, + super.$removeJoinBuilderFromRootComposer, + }); + ColumnOrderings get id => $composableBuilder( + column: $table.id, builder: (column) => ColumnOrderings(column)); + + ColumnOrderings get operation => $composableBuilder( + column: $table.operation, builder: (column) => ColumnOrderings(column)); + + ColumnOrderings get payload => $composableBuilder( + column: $table.payload, builder: (column) => ColumnOrderings(column)); + + ColumnOrderings get sessionId => $composableBuilder( + column: $table.sessionId, builder: (column) => ColumnOrderings(column)); + + ColumnOrderings get createdAt => $composableBuilder( + column: $table.createdAt, builder: (column) => ColumnOrderings(column)); + + ColumnOrderings get synced => $composableBuilder( + column: $table.synced, builder: (column) => ColumnOrderings(column)); + + ColumnOrderings get retryCount => $composableBuilder( + column: $table.retryCount, builder: (column) => ColumnOrderings(column)); + + ColumnOrderings get lastError => $composableBuilder( + column: $table.lastError, builder: (column) => ColumnOrderings(column)); +} + +class $$SyncQueueTableAnnotationComposer + extends Composer<_$AppDatabase, $SyncQueueTable> { + $$SyncQueueTableAnnotationComposer({ + required super.$db, + required super.$table, + super.joinBuilder, + super.$addJoinBuilderToRootComposer, + super.$removeJoinBuilderFromRootComposer, + }); + GeneratedColumn get id => + $composableBuilder(column: $table.id, builder: (column) => column); + + GeneratedColumn get operation => + $composableBuilder(column: $table.operation, builder: (column) => column); + + GeneratedColumn get payload => + $composableBuilder(column: $table.payload, builder: (column) => column); + + GeneratedColumn get sessionId => + $composableBuilder(column: $table.sessionId, builder: (column) => column); + + GeneratedColumn get createdAt => + $composableBuilder(column: $table.createdAt, builder: (column) => column); + + GeneratedColumn get synced => + $composableBuilder(column: $table.synced, builder: (column) => column); + + GeneratedColumn get retryCount => $composableBuilder( + column: $table.retryCount, builder: (column) => column); + + GeneratedColumn get lastError => + $composableBuilder(column: $table.lastError, builder: (column) => column); +} + +class $$SyncQueueTableTableManager extends RootTableManager< + _$AppDatabase, + $SyncQueueTable, + SyncQueueData, + $$SyncQueueTableFilterComposer, + $$SyncQueueTableOrderingComposer, + $$SyncQueueTableAnnotationComposer, + $$SyncQueueTableCreateCompanionBuilder, + $$SyncQueueTableUpdateCompanionBuilder, + ( + SyncQueueData, + BaseReferences<_$AppDatabase, $SyncQueueTable, SyncQueueData> + ), + SyncQueueData, + PrefetchHooks Function()> { + $$SyncQueueTableTableManager(_$AppDatabase db, $SyncQueueTable table) + : super(TableManagerState( + db: db, + table: table, + createFilteringComposer: () => + $$SyncQueueTableFilterComposer($db: db, $table: table), + createOrderingComposer: () => + $$SyncQueueTableOrderingComposer($db: db, $table: table), + createComputedFieldComposer: () => + $$SyncQueueTableAnnotationComposer($db: db, $table: table), + updateCompanionCallback: ({ + Value id = const Value.absent(), + Value operation = const Value.absent(), + Value payload = const Value.absent(), + Value sessionId = const Value.absent(), + Value createdAt = const Value.absent(), + Value synced = const Value.absent(), + Value retryCount = const Value.absent(), + Value lastError = const Value.absent(), + }) => + SyncQueueCompanion( + id: id, + operation: operation, + payload: payload, + sessionId: sessionId, + createdAt: createdAt, + synced: synced, + retryCount: retryCount, + lastError: lastError, + ), + createCompanionCallback: ({ + Value id = const Value.absent(), + required String operation, + required String payload, + Value sessionId = const Value.absent(), + required DateTime createdAt, + Value synced = const Value.absent(), + Value retryCount = const Value.absent(), + Value lastError = const Value.absent(), + }) => + SyncQueueCompanion.insert( + id: id, + operation: operation, + payload: payload, + sessionId: sessionId, + createdAt: createdAt, + synced: synced, + retryCount: retryCount, + lastError: lastError, + ), + withReferenceMapper: (p0) => p0 + .map((e) => (e.readTable(table), BaseReferences(db, table, e))) + .toList(), + prefetchHooksCallback: null, + )); +} + +typedef $$SyncQueueTableProcessedTableManager = ProcessedTableManager< + _$AppDatabase, + $SyncQueueTable, + SyncQueueData, + $$SyncQueueTableFilterComposer, + $$SyncQueueTableOrderingComposer, + $$SyncQueueTableAnnotationComposer, + $$SyncQueueTableCreateCompanionBuilder, + $$SyncQueueTableUpdateCompanionBuilder, + ( + SyncQueueData, + BaseReferences<_$AppDatabase, $SyncQueueTable, SyncQueueData> + ), + SyncQueueData, + PrefetchHooks Function()>; + +class $AppDatabaseManager { + final _$AppDatabase _db; + $AppDatabaseManager(this._db); + $$SessionsTableTableManager get sessions => + $$SessionsTableTableManager(_db, _db.sessions); + $$MessagesTableTableManager get messages => + $$MessagesTableTableManager(_db, _db.messages); + $$AgentsTableTableManager get agents => + $$AgentsTableTableManager(_db, _db.agents); + $$ApprovalsTableTableManager get approvals => + $$ApprovalsTableTableManager(_db, _db.approvals); + $$SyncQueueTableTableManager get syncQueue => + $$SyncQueueTableTableManager(_db, _db.syncQueue); +} diff --git a/apps/mobile/lib/core/storage/preferences.dart b/apps/mobile/lib/core/storage/preferences.dart new file mode 100644 index 0000000..6847249 --- /dev/null +++ b/apps/mobile/lib/core/storage/preferences.dart @@ -0,0 +1,77 @@ +import 'package:flutter/material.dart'; +import 'package:hive_flutter/hive_flutter.dart'; + +const String _kBoxName = 'preferences'; +const String _kThemeMode = 'theme_mode'; +const String _kDefaultAgentId = 'default_agent_id'; +const String _kNotificationsEnabled = 'notifications_enabled'; +const String _kBridgeUrl = 'bridge_url'; +const String _kHighContrast = 'high_contrast'; + +/// App preferences backed by a Hive key-value box. +/// No HiveType annotations are needed — this class uses a dynamic string-keyed box. +class AppPreferences { + late Box _box; + + Future init() async { + _box = await Hive.openBox(_kBoxName); + } + + ThemeMode getThemeMode() { + final value = _box.get(_kThemeMode, defaultValue: 'system') as String; + return switch (value) { + 'light' => ThemeMode.light, + 'dark' => ThemeMode.dark, + _ => ThemeMode.system, + }; + } + + Future setThemeMode(ThemeMode mode) async { + final value = switch (mode) { + ThemeMode.light => 'light', + ThemeMode.dark => 'dark', + ThemeMode.system => 'system', + }; + await _box.put(_kThemeMode, value); + } + + String? getDefaultAgentId() { + return _box.get(_kDefaultAgentId) as String?; + } + + Future setDefaultAgentId(String? id) async { + if (id == null) { + await _box.delete(_kDefaultAgentId); + } else { + await _box.put(_kDefaultAgentId, id); + } + } + + bool getNotificationsEnabled() { + return _box.get(_kNotificationsEnabled, defaultValue: true) as bool; + } + + Future setNotificationsEnabled(bool enabled) async { + await _box.put(_kNotificationsEnabled, enabled); + } + + String? getBridgeUrl() { + return _box.get(_kBridgeUrl) as String?; + } + + Future setBridgeUrl(String? url) async { + if (url == null) { + await _box.delete(_kBridgeUrl); + } else { + await _box.put(_kBridgeUrl, url); + } + } + + bool getHighContrast() { + return _box.get(_kHighContrast, defaultValue: false) as bool; + } + + Future setHighContrast(bool val) async { + await _box.put(_kHighContrast, val); + } +} diff --git a/apps/mobile/lib/core/storage/tables/agents_table.dart b/apps/mobile/lib/core/storage/tables/agents_table.dart new file mode 100644 index 0000000..d7c1c50 --- /dev/null +++ b/apps/mobile/lib/core/storage/tables/agents_table.dart @@ -0,0 +1,29 @@ +import 'package:drift/drift.dart'; + +/// Stores configured agent connections. +class Agents extends Table { + TextColumn get id => text()(); + TextColumn get displayName => text()(); + + /// "claude-code" | "opencode" | "aider" | "goose" | "custom" + TextColumn get agentType => text()(); + + /// WebSocket bridge URL, e.g. "wss://100.78.42.15:3000" + TextColumn get bridgeUrl => text()(); + + /// Encrypted bridge auth token. + TextColumn get authToken => text()(); + + TextColumn get workingDirectory => text().nullable()(); + + /// "connected" | "disconnected" | "inactive" + TextColumn get status => + text().withDefault(const Constant('disconnected'))(); + + DateTimeColumn get lastConnectedAt => dateTime().nullable()(); + DateTimeColumn get createdAt => dateTime()(); + DateTimeColumn get updatedAt => dateTime()(); + + @override + Set get primaryKey => {id}; +} diff --git a/apps/mobile/lib/core/storage/tables/approvals_table.dart b/apps/mobile/lib/core/storage/tables/approvals_table.dart new file mode 100644 index 0000000..4a125d6 --- /dev/null +++ b/apps/mobile/lib/core/storage/tables/approvals_table.dart @@ -0,0 +1,36 @@ +import 'package:drift/drift.dart'; + +import 'sessions_table.dart'; + +/// Stores tool call approval history. +class Approvals extends Table { + TextColumn get id => text()(); + TextColumn get sessionId => text().references(Sessions, #id)(); + TextColumn get tool => text()(); + TextColumn get description => text()(); + + /// JSON: tool parameters. + TextColumn get params => text()(); + + /// Agent's explanation. + TextColumn get reasoning => text().nullable()(); + + /// "low" | "medium" | "high" | "critical" + TextColumn get riskLevel => text()(); + + /// "approved" | "rejected" | "modified" | "pending" + TextColumn get decision => text()(); + + /// User's modification instructions. + TextColumn get modifications => text().nullable()(); + + /// JSON: tool execution result. + TextColumn get result => text().nullable()(); + + DateTimeColumn get createdAt => dateTime()(); + DateTimeColumn get decidedAt => dateTime().nullable()(); + BoolColumn get synced => boolean().withDefault(const Constant(true))(); + + @override + Set get primaryKey => {id}; +} diff --git a/apps/mobile/lib/core/storage/tables/messages_table.dart b/apps/mobile/lib/core/storage/tables/messages_table.dart new file mode 100644 index 0000000..ec664b6 --- /dev/null +++ b/apps/mobile/lib/core/storage/tables/messages_table.dart @@ -0,0 +1,29 @@ +import 'package:drift/drift.dart'; + +import 'sessions_table.dart'; + +/// Stores chat messages within sessions. +class Messages extends Table { + TextColumn get id => text()(); + TextColumn get sessionId => text().references(Sessions, #id)(); + + /// "user" | "agent" | "system" + TextColumn get role => text()(); + + /// Full message text (markdown). + TextColumn get content => text()(); + + /// "text" | "tool_call" | "tool_result" | "system" + TextColumn get messageType => + text().withDefault(const Constant('text'))(); + + /// JSON: token count, tool info, etc. + TextColumn get metadata => text().nullable()(); + + DateTimeColumn get createdAt => dateTime()(); + DateTimeColumn get updatedAt => dateTime()(); + BoolColumn get synced => boolean().withDefault(const Constant(true))(); + + @override + Set get primaryKey => {id}; +} diff --git a/apps/mobile/lib/core/storage/tables/sessions_table.dart b/apps/mobile/lib/core/storage/tables/sessions_table.dart new file mode 100644 index 0000000..e9681be --- /dev/null +++ b/apps/mobile/lib/core/storage/tables/sessions_table.dart @@ -0,0 +1,22 @@ +import 'package:drift/drift.dart'; + +/// Stores agent chat sessions. +class Sessions extends Table { + TextColumn get id => text()(); + TextColumn get agentType => text()(); + TextColumn get agentId => text().nullable()(); + TextColumn get title => text().withDefault(const Constant(''))(); + TextColumn get workingDirectory => text()(); + TextColumn get branch => text().nullable()(); + + /// "active" | "paused" | "closed" + TextColumn get status => text()(); + + DateTimeColumn get createdAt => dateTime()(); + DateTimeColumn get lastMessageAt => dateTime().nullable()(); + DateTimeColumn get updatedAt => dateTime()(); + BoolColumn get synced => boolean().withDefault(const Constant(true))(); + + @override + Set get primaryKey => {id}; +} diff --git a/apps/mobile/lib/core/storage/tables/sync_queue_table.dart b/apps/mobile/lib/core/storage/tables/sync_queue_table.dart new file mode 100644 index 0000000..2141fd5 --- /dev/null +++ b/apps/mobile/lib/core/storage/tables/sync_queue_table.dart @@ -0,0 +1,19 @@ +import 'package:drift/drift.dart'; + +/// Offline mutation queue — persists operations until they can be flushed +/// to the bridge server after reconnection. +class SyncQueue extends Table { + IntColumn get id => integer().autoIncrement()(); + + /// "send_message" | "approve_tool" | "git_command" + TextColumn get operation => text()(); + + /// JSON: full operation payload. + TextColumn get payload => text()(); + + TextColumn get sessionId => text().nullable()(); + DateTimeColumn get createdAt => dateTime()(); + BoolColumn get synced => boolean().withDefault(const Constant(false))(); + IntColumn get retryCount => integer().withDefault(const Constant(0))(); + TextColumn get lastError => text().nullable()(); +} diff --git a/apps/mobile/lib/core/sync/conflict_resolver.dart b/apps/mobile/lib/core/sync/conflict_resolver.dart new file mode 100644 index 0000000..bdfa996 --- /dev/null +++ b/apps/mobile/lib/core/sync/conflict_resolver.dart @@ -0,0 +1,58 @@ +import 'package:flutter/material.dart'; + +/// Conflict resolution strategies for offline sync. +class ConflictResolver { + const ConflictResolver(); + + /// Last-write-wins: return whichever record has the later [updatedAt]. + /// If both are equal, prefer [remote]. + T resolve(T local, T remote) { + if (local.updatedAt == null) return remote; + if (remote.updatedAt == null) return local; + return local.updatedAt!.isAfter(remote.updatedAt!) ? local : remote; + } + + /// Show a dialog asking the user which version to keep. + /// Returns the chosen record. + Future resolveWithUserPrompt( + T local, + T remote, + BuildContext context, + ) async { + final choice = await showDialog<_ConflictChoice>( + context: context, + barrierDismissible: false, + builder: (ctx) => AlertDialog( + title: const Text('Sync Conflict'), + content: const Text( + 'This item was modified both locally and on the server. ' + 'Which version would you like to keep?', + ), + actions: [ + TextButton( + onPressed: () => + Navigator.of(ctx).pop(_ConflictChoice.local), + child: const Text('Keep Mine'), + ), + TextButton( + onPressed: () => + Navigator.of(ctx).pop(_ConflictChoice.remote), + child: const Text('Use Server Version'), + ), + ], + ), + ); + + return switch (choice) { + _ConflictChoice.local => local, + _ => remote, + }; + } +} + +enum _ConflictChoice { local, remote } + +/// Mixin contract for types that expose an [updatedAt] timestamp. +abstract interface class _HasUpdatedAt { + DateTime? get updatedAt; +} diff --git a/apps/mobile/lib/core/sync/sync_queue.dart b/apps/mobile/lib/core/sync/sync_queue.dart new file mode 100644 index 0000000..524a2b3 --- /dev/null +++ b/apps/mobile/lib/core/sync/sync_queue.dart @@ -0,0 +1,63 @@ +import 'dart:convert'; + +import 'package:drift/drift.dart'; + +import '../network/websocket_messages.dart'; +import '../network/websocket_service.dart'; +import '../storage/daos/sync_dao.dart'; +import '../storage/database.dart'; +import '../storage/tables/sync_queue_table.dart'; + +/// Manages an offline-first mutation queue backed by [SyncDao]. +/// Operations enqueued while disconnected are replayed on reconnect via [flush]. +class SyncQueueService { + SyncQueueService({required AppDatabase database}) + : _dao = database.syncDao; + + final SyncDao _dao; + + Future enqueue( + String operation, + Map payload, { + String? sessionId, + }) async { + await _dao.enqueue( + SyncQueueCompanion( + operation: Value(operation), + payload: Value(jsonEncode(payload)), + sessionId: Value(sessionId), + createdAt: Value(DateTime.now().toUtc()), + ), + ); + } + + /// Dequeue all pending items and send them over [ws]. + /// Items that succeed are marked as synced; failures increment retry count. + Future flush(WebSocketService ws) async { + final pending = await _dao.getPendingItems(); + for (final item in pending) { + try { + final payloadMap = + jsonDecode(item.payload) as Map; + final message = BridgeMessage( + type: BridgeMessageType.message, + timestamp: DateTime.now().toUtc(), + payload: { + 'operation': item.operation, + 'data': payloadMap, + if (item.sessionId != null) 'session_id': item.sessionId, + }, + ); + ws.send(message); + await _dao.markSynced(item.id); + } catch (e) { + await _dao.incrementRetry(item.id, e.toString()); + } + } + } + + Future getPendingCount() async { + final items = await _dao.getPendingItems(); + return items.length; + } +} diff --git a/apps/mobile/lib/core/sync/sync_service.dart b/apps/mobile/lib/core/sync/sync_service.dart new file mode 100644 index 0000000..09cf5c3 --- /dev/null +++ b/apps/mobile/lib/core/sync/sync_service.dart @@ -0,0 +1,48 @@ +import 'dart:async'; + +import '../network/connection_state.dart'; +import '../network/websocket_service.dart'; +import '../notifications/notification_center.dart'; +import 'sync_queue.dart'; + +/// Orchestrates sync on reconnection. +/// Listens to [WebSocketService.connectionStatus] and triggers queue flush +/// when the connection is (re-)established. +class SyncService { + SyncService({ + required WebSocketService webSocketService, + required SyncQueueService syncQueue, + required NotificationCenter notificationCenter, + }) : _ws = webSocketService, + _syncQueue = syncQueue, + _notificationCenter = notificationCenter; + + final WebSocketService _ws; + final SyncQueueService _syncQueue; + final NotificationCenter _notificationCenter; + + StreamSubscription? _statusSubscription; + bool _running = false; + + void start() { + if (_running) return; + _running = true; + + _statusSubscription = _ws.connectionStatus.listen((status) async { + if (status == ConnectionStatus.connected) { + await _onReconnected(); + } + }); + } + + Future _onReconnected() async { + // Flush queued messages. + await _syncQueue.flush(_ws); + } + + void stop() { + _running = false; + _statusSubscription?.cancel(); + _statusSubscription = null; + } +} diff --git a/apps/mobile/lib/features/agents/domain/providers/agent_provider.dart b/apps/mobile/lib/features/agents/domain/providers/agent_provider.dart new file mode 100644 index 0000000..0e562c8 --- /dev/null +++ b/apps/mobile/lib/features/agents/domain/providers/agent_provider.dart @@ -0,0 +1,155 @@ +import 'dart:async'; +import 'dart:convert'; + +import 'package:flutter_riverpod/flutter_riverpod.dart'; +import 'package:drift/drift.dart' show Value; +import 'package:web_socket_channel/web_socket_channel.dart'; +import 'package:uuid/uuid.dart'; + +import '../../../../core/models/agent_models.dart'; +import '../../../../core/providers/database_provider.dart'; +import '../../../../core/storage/database.dart'; +import '../../../../core/storage/tables/agents_table.dart'; + +const _uuid = Uuid(); + +// --------------------------------------------------------------------------- +// Agents AsyncNotifier +// --------------------------------------------------------------------------- + +class AgentNotifier extends AsyncNotifier> { + @override + Future> build() async { + return _load(); + } + + Future> _load() async { + final db = ref.read(databaseProvider); + final rows = await db.select(db.agents).get(); + return rows.map(_rowToModel).toList(); + } + + AgentConfig _rowToModel(dynamic row) { + return AgentConfig( + id: row.id as String, + displayName: row.displayName as String, + type: AgentType.values.firstWhere( + (e) => e.name == (row.agentType as String), + orElse: () => AgentType.custom, + ), + bridgeUrl: row.bridgeUrl as String, + authToken: row.authToken as String, + workingDirectory: row.workingDirectory as String?, + status: AgentConnectionStatus.values.firstWhere( + (e) => e.name == (row.status as String), + orElse: () => AgentConnectionStatus.disconnected, + ), + lastConnectedAt: row.lastConnectedAt as DateTime?, + createdAt: row.createdAt as DateTime, + updatedAt: row.updatedAt as DateTime, + ); + } + + Future load() async { + state = const AsyncValue.loading(); + state = await AsyncValue.guard(_load); + } + + Future add(AgentConfig agent) async { + final db = ref.read(databaseProvider); + await db.into(db.agents).insert(AgentsCompanion( + id: Value(agent.id), + displayName: Value(agent.displayName), + agentType: Value(agent.type.name), + bridgeUrl: Value(agent.bridgeUrl), + authToken: Value(agent.authToken), + workingDirectory: Value(agent.workingDirectory), + status: Value(agent.status.name), + lastConnectedAt: Value(agent.lastConnectedAt), + createdAt: Value(agent.createdAt), + updatedAt: Value(agent.updatedAt), + )); + await load(); + } + + Future updateAgent(AgentConfig agent) async { + final db = ref.read(databaseProvider); + await db.into(db.agents).insertOnConflictUpdate(AgentsCompanion( + id: Value(agent.id), + displayName: Value(agent.displayName), + agentType: Value(agent.type.name), + bridgeUrl: Value(agent.bridgeUrl), + authToken: Value(agent.authToken), + workingDirectory: Value(agent.workingDirectory), + status: Value(agent.status.name), + lastConnectedAt: Value(agent.lastConnectedAt), + createdAt: Value(agent.createdAt), + updatedAt: Value(DateTime.now()), + )); + await load(); + } + + Future delete(String id) async { + final db = ref.read(databaseProvider); + await (db.delete(db.agents)..where((a) => a.id.equals(id))).go(); + await load(); + } + + /// Attempts to connect to the given bridge and verifies a `connection_ack` + /// response. Returns `true` on success, `false` on failure. + Future testConnection(String bridgeUrl, String token) async { + WebSocketChannel? channel; + try { + final uri = Uri.parse(bridgeUrl); + channel = WebSocketChannel.connect(uri); + await channel.ready; + + channel.sink.add(jsonEncode({ + 'type': 'auth', + 'payload': { + 'token': token, + 'client_version': '0.1.0', + 'platform': 'flutter', + }, + 'timestamp': DateTime.now().toIso8601String(), + 'id': 'test-${_uuid.v4()}', + })); + + // Wait up to 5 seconds for connection_ack. + final completer = Completer(); + late StreamSubscription sub; + final timeout = Timer(const Duration(seconds: 5), () { + if (!completer.isCompleted) completer.complete(false); + }); + + sub = channel.stream.listen( + (data) { + try { + final json = jsonDecode(data as String) as Map; + if (json['type'] == 'connection_ack') { + if (!completer.isCompleted) completer.complete(true); + } + } catch (_) {} + }, + onError: (_) { + if (!completer.isCompleted) completer.complete(false); + }, + onDone: () { + if (!completer.isCompleted) completer.complete(false); + }, + ); + + final result = await completer.future; + timeout.cancel(); + sub.cancel(); + await channel.sink.close(); + return result; + } catch (_) { + await channel?.sink.close(); + return false; + } + } +} + +final agentsProvider = + AsyncNotifierProvider>(AgentNotifier.new); diff --git a/apps/mobile/lib/features/agents/presentation/screens/agent_config_screen.dart b/apps/mobile/lib/features/agents/presentation/screens/agent_config_screen.dart new file mode 100644 index 0000000..d5ac5ab --- /dev/null +++ b/apps/mobile/lib/features/agents/presentation/screens/agent_config_screen.dart @@ -0,0 +1,269 @@ +import 'package:flutter/material.dart'; +import 'package:flutter_riverpod/flutter_riverpod.dart'; +import 'package:go_router/go_router.dart'; +import 'package:mobile_scanner/mobile_scanner.dart'; +import 'package:uuid/uuid.dart'; + +import '../../../../core/models/agent_models.dart'; +import '../../domain/providers/agent_provider.dart'; + +const _uuid = Uuid(); + +/// Create or edit an [AgentConfig]. +/// +/// Pass an existing [AgentConfig] via route `extra` for edit mode. +class AgentConfigScreen extends ConsumerStatefulWidget { + final AgentConfig? existingAgent; + + const AgentConfigScreen({super.key, this.existingAgent}); + + @override + ConsumerState createState() => _AgentConfigScreenState(); +} + +class _AgentConfigScreenState extends ConsumerState { + final _formKey = GlobalKey(); + late final TextEditingController _nameController; + late final TextEditingController _bridgeUrlController; + late final TextEditingController _tokenController; + late AgentType _agentType; + bool _obscureToken = true; + bool _isTesting = false; + bool _isSaving = false; + + bool get _isEditMode => widget.existingAgent != null; + + @override + void initState() { + super.initState(); + final a = widget.existingAgent; + _nameController = TextEditingController(text: a?.displayName ?? ''); + _bridgeUrlController = TextEditingController(text: a?.bridgeUrl ?? ''); + _tokenController = TextEditingController(text: a?.authToken ?? ''); + _agentType = a?.type ?? AgentType.claudeCode; + } + + @override + void dispose() { + _nameController.dispose(); + _bridgeUrlController.dispose(); + _tokenController.dispose(); + super.dispose(); + } + + Future _save() async { + if (!(_formKey.currentState?.validate() ?? false)) return; + setState(() => _isSaving = true); + + final now = DateTime.now(); + final agent = AgentConfig( + id: widget.existingAgent?.id ?? _uuid.v4(), + displayName: _nameController.text.trim(), + type: _agentType, + bridgeUrl: _bridgeUrlController.text.trim(), + authToken: _tokenController.text.trim(), + status: AgentConnectionStatus.disconnected, + createdAt: widget.existingAgent?.createdAt ?? now, + updatedAt: now, + ); + + if (_isEditMode) { + await ref.read(agentsProvider.notifier).updateAgent(agent); + } else { + await ref.read(agentsProvider.notifier).add(agent); + } + + if (mounted) { + setState(() => _isSaving = false); + context.pop(); + } + } + + Future _delete() async { + final id = widget.existingAgent!.id; + await ref.read(agentsProvider.notifier).delete(id); + if (mounted) context.pop(); + } + + Future _testConnection() async { + setState(() => _isTesting = true); + final ok = await ref.read(agentsProvider.notifier).testConnection( + _bridgeUrlController.text.trim(), + _tokenController.text.trim(), + ); + if (mounted) { + setState(() => _isTesting = false); + ScaffoldMessenger.of(context).showSnackBar( + SnackBar( + content: Text(ok ? 'Connection successful' : 'Connection failed'), + backgroundColor: + ok ? const Color(0xFF4CAF50) : const Color(0xFFF44747), + ), + ); + } + } + + Future _scanQr() async { + final result = await Navigator.push( + context, + MaterialPageRoute(builder: (_) => const _QrScanPage()), + ); + if (result != null) { + _bridgeUrlController.text = result; + } + } + + @override + Widget build(BuildContext context) { + return Scaffold( + appBar: AppBar( + title: Text(_isEditMode ? 'Edit Agent' : 'Add Agent'), + actions: [ + if (_isEditMode) + PopupMenuButton( + onSelected: (value) { + if (value == 'delete') _delete(); + }, + itemBuilder: (_) => [ + const PopupMenuItem( + value: 'delete', + child: Text('Delete'), + ), + ], + ), + TextButton( + onPressed: _isSaving ? null : _save, + child: _isSaving + ? const SizedBox( + width: 18, + height: 18, + child: CircularProgressIndicator(strokeWidth: 2), + ) + : const Text('Save'), + ), + ], + ), + body: Form( + key: _formKey, + child: ListView( + padding: const EdgeInsets.all(16), + children: [ + // Display name + TextFormField( + controller: _nameController, + decoration: const InputDecoration(labelText: 'Display Name'), + validator: (v) => + (v == null || v.trim().isEmpty) ? 'Required' : null, + ), + const SizedBox(height: 16), + + // Agent type dropdown + DropdownButtonFormField( + value: _agentType, + decoration: const InputDecoration(labelText: 'Agent Type'), + dropdownColor: const Color(0xFF252526), + items: AgentType.values + .map((t) => DropdownMenuItem( + value: t, + child: Text(t.name), + )) + .toList(), + onChanged: (v) => setState(() => _agentType = v!), + ), + const SizedBox(height: 16), + + // Bridge URL + Row( + children: [ + Expanded( + child: TextFormField( + controller: _bridgeUrlController, + decoration: const InputDecoration( + labelText: 'Bridge URL', + hintText: 'wss://host:3000', + ), + validator: (v) => + (v == null || v.trim().isEmpty) ? 'Required' : null, + keyboardType: TextInputType.url, + ), + ), + const SizedBox(width: 8), + IconButton( + tooltip: 'Scan QR', + icon: const Icon(Icons.qr_code_scanner), + onPressed: _scanQr, + ), + ], + ), + const SizedBox(height: 16), + + // Auth token (obscured) + TextFormField( + controller: _tokenController, + obscureText: _obscureToken, + decoration: InputDecoration( + labelText: 'Auth Token', + suffixIcon: IconButton( + icon: Icon(_obscureToken + ? Icons.visibility_off + : Icons.visibility), + onPressed: () => + setState(() => _obscureToken = !_obscureToken), + ), + ), + validator: (v) => + (v == null || v.trim().isEmpty) ? 'Required' : null, + ), + const SizedBox(height: 24), + + // Test connection button + OutlinedButton.icon( + onPressed: _isTesting ? null : _testConnection, + icon: _isTesting + ? const SizedBox( + width: 16, + height: 16, + child: CircularProgressIndicator(strokeWidth: 2), + ) + : const Icon(Icons.wifi_tethering, size: 18), + label: const Text('Test Connection'), + ), + ], + ), + ), + ); + } +} + +// --------------------------------------------------------------------------- +// QR scanner page +// --------------------------------------------------------------------------- + +class _QrScanPage extends StatefulWidget { + const _QrScanPage(); + + @override + State<_QrScanPage> createState() => _QrScanPageState(); +} + +class _QrScanPageState extends State<_QrScanPage> { + bool _scanned = false; + + @override + Widget build(BuildContext context) { + return Scaffold( + appBar: AppBar(title: const Text('Scan QR Code')), + body: MobileScanner( + onDetect: (capture) { + if (_scanned) return; + final barcode = capture.barcodes.firstOrNull; + final value = barcode?.rawValue; + if (value != null && value.isNotEmpty) { + _scanned = true; + Navigator.of(context).pop(value); + } + }, + ), + ); + } +} diff --git a/apps/mobile/lib/features/agents/presentation/screens/agent_list_screen.dart b/apps/mobile/lib/features/agents/presentation/screens/agent_list_screen.dart new file mode 100644 index 0000000..74b547f --- /dev/null +++ b/apps/mobile/lib/features/agents/presentation/screens/agent_list_screen.dart @@ -0,0 +1,117 @@ +import 'package:flutter/material.dart'; +import 'package:flutter_riverpod/flutter_riverpod.dart'; +import 'package:go_router/go_router.dart'; + +import '../../domain/providers/agent_provider.dart'; +import '../widgets/agent_card.dart'; + +/// Lists all configured agents with swipe-to-delete and an add FAB. +class AgentListScreen extends ConsumerStatefulWidget { + const AgentListScreen({super.key}); + + @override + ConsumerState createState() => _AgentListScreenState(); +} + +class _AgentListScreenState extends ConsumerState { + @override + void initState() { + super.initState(); + WidgetsBinding.instance.addPostFrameCallback((_) { + ref.read(agentsProvider.notifier).load(); + }); + } + + Future _delete(String id, String name) async { + await ref.read(agentsProvider.notifier).delete(id); + if (mounted) { + ScaffoldMessenger.of(context).showSnackBar( + SnackBar( + content: Text('$name removed'), + action: SnackBarAction( + label: 'Undo', + onPressed: () { + // Re-adding would require keeping the deleted model around; + // for now just refresh — a full undo is a future enhancement. + ref.read(agentsProvider.notifier).load(); + }, + ), + ), + ); + } + } + + @override + Widget build(BuildContext context) { + final agentsAsync = ref.watch(agentsProvider); + + return Scaffold( + appBar: AppBar(title: const Text('Agents')), + floatingActionButton: FloatingActionButton.extended( + onPressed: () => context.push('/home/agents/config'), + icon: const Icon(Icons.add), + label: const Text('Add Agent'), + ), + body: agentsAsync.when( + loading: () => const Center(child: CircularProgressIndicator()), + error: (e, _) => Center(child: Text('Error: $e')), + data: (agents) { + if (agents.isEmpty) { + return const _EmptyState(); + } + + return ListView.builder( + padding: const EdgeInsets.only(top: 8, bottom: 80), + itemCount: agents.length, + itemBuilder: (context, index) { + final agent = agents[index]; + return Dismissible( + key: Key(agent.id), + direction: DismissDirection.endToStart, + background: Container( + alignment: Alignment.centerRight, + color: const Color(0xFFF44747), + padding: const EdgeInsets.only(right: 20), + child: const Icon(Icons.delete_outline, + color: Colors.white), + ), + onDismissed: (_) => _delete(agent.id, agent.displayName), + child: AgentCard( + agent: agent, + onTap: () => + context.push('/home/agents/config', extra: agent), + ), + ); + }, + ); + }, + ), + ); + } +} + +class _EmptyState extends StatelessWidget { + const _EmptyState(); + + @override + Widget build(BuildContext context) { + return Center( + child: Column( + mainAxisSize: MainAxisSize.min, + children: const [ + Icon(Icons.smart_toy_outlined, size: 64, color: Color(0xFF9E9E9E)), + SizedBox(height: 16), + Text( + 'No agents configured', + style: TextStyle(fontSize: 16, color: Color(0xFF9E9E9E)), + ), + SizedBox(height: 8), + Text( + 'Tap + Add Agent to get started.', + style: TextStyle(fontSize: 13, color: Color(0xFF666666)), + ), + ], + ), + ); + } +} diff --git a/apps/mobile/lib/features/agents/presentation/widgets/agent_card.dart b/apps/mobile/lib/features/agents/presentation/widgets/agent_card.dart new file mode 100644 index 0000000..897bfc0 --- /dev/null +++ b/apps/mobile/lib/features/agents/presentation/widgets/agent_card.dart @@ -0,0 +1,98 @@ +import 'package:flutter/material.dart'; + +import '../../../../core/models/agent_models.dart'; +import '../../../../shared/utils/date_formatter.dart'; + +/// Card for a configured [AgentConfig] in the agent list. +class AgentCard extends StatelessWidget { + final AgentConfig agent; + final VoidCallback onTap; + + const AgentCard({super.key, required this.agent, required this.onTap}); + + IconData _iconForType(AgentType type) { + return switch (type) { + AgentType.claudeCode => Icons.auto_awesome, + AgentType.openCode => Icons.code, + AgentType.aider => Icons.terminal, + AgentType.goose => Icons.rocket_launch_outlined, + AgentType.custom => Icons.settings_input_component, + }; + } + + Color _statusColor(AgentConnectionStatus status) { + return switch (status) { + AgentConnectionStatus.connected => const Color(0xFF4CAF50), + AgentConnectionStatus.inactive => const Color(0xFFFF9800), + AgentConnectionStatus.disconnected => const Color(0xFF9E9E9E), + }; + } + + @override + Widget build(BuildContext context) { + final statusColor = _statusColor(agent.status); + final lastConnected = agent.lastConnectedAt != null + ? DateFormatter.formatRelative(agent.lastConnectedAt!) + : 'Never'; + + // Truncate long bridge URLs. + final bridgeDisplay = agent.bridgeUrl.length > 40 + ? '${agent.bridgeUrl.substring(0, 37)}…' + : agent.bridgeUrl; + + return Card( + margin: const EdgeInsets.symmetric(horizontal: 12, vertical: 4), + child: InkWell( + onTap: onTap, + borderRadius: BorderRadius.circular(8), + child: ListTile( + leading: CircleAvatar( + backgroundColor: const Color(0xFF252526), + child: Icon( + _iconForType(agent.type), + size: 18, + color: const Color(0xFF569CD6), + ), + ), + title: Text( + agent.displayName, + style: const TextStyle( + fontSize: 14, + fontWeight: FontWeight.w500, + color: Color(0xFFD4D4D4), + ), + ), + subtitle: Column( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + Text( + bridgeDisplay, + style: const TextStyle( + fontSize: 11, + fontFamily: 'JetBrainsMono', + color: Color(0xFF9E9E9E), + ), + ), + Text( + 'Last connected: $lastConnected', + style: const TextStyle( + fontSize: 10, + color: Color(0xFF9E9E9E), + ), + ), + ], + ), + trailing: Container( + width: 8, + height: 8, + decoration: BoxDecoration( + color: statusColor, + shape: BoxShape.circle, + ), + ), + isThreeLine: true, + ), + ), + ); + } +} diff --git a/apps/mobile/lib/features/approvals/domain/providers/approval_provider.dart b/apps/mobile/lib/features/approvals/domain/providers/approval_provider.dart new file mode 100644 index 0000000..60713f3 --- /dev/null +++ b/apps/mobile/lib/features/approvals/domain/providers/approval_provider.dart @@ -0,0 +1,199 @@ +import 'dart:async'; +import 'dart:convert'; + +import 'package:flutter_riverpod/flutter_riverpod.dart'; + +import '../../../../core/models/message_models.dart'; +import '../../../../core/network/websocket_messages.dart'; +import '../../../../core/providers/database_provider.dart'; +import '../../../../core/providers/websocket_provider.dart'; +import '../../../../core/storage/database.dart'; +import '../../../../core/storage/tables/approvals_table.dart'; +import 'package:drift/drift.dart' show Value; +import 'package:uuid/uuid.dart'; + +const _uuid = Uuid(); + +// --------------------------------------------------------------------------- +// Pending approvals (in-memory list) +// --------------------------------------------------------------------------- + +class PendingApprovalsNotifier extends StateNotifier> { + PendingApprovalsNotifier(this._ref) : super([]) { + _listen(); + } + + final Ref _ref; + StreamSubscription? _sub; + + void _listen() { + final service = _ref.read(webSocketServiceProvider); + _sub = service.messages.listen((msg) { + if (msg.type == BridgeMessageType.approvalRequired) { + try { + final toolCall = _parseToolCall(msg.payload); + state = [...state, toolCall]; + } catch (_) { + // Malformed payload — ignore. + } + } + }); + } + + ToolCall _parseToolCall(Map payload) { + return ToolCall( + id: payload['tool_call_id'] as String? ?? _uuid.v4(), + sessionId: payload['session_id'] as String? ?? '', + tool: payload['tool'] as String? ?? 'unknown', + params: (payload['params'] as Map?) ?? {}, + description: payload['description'] as String?, + reasoning: payload['reasoning'] as String?, + riskLevel: _parseRisk(payload['risk_level'] as String?), + decision: ApprovalDecision.pending, + createdAt: DateTime.now(), + ); + } + + RiskLevel _parseRisk(String? value) { + return switch (value) { + 'medium' => RiskLevel.medium, + 'high' => RiskLevel.high, + 'critical' => RiskLevel.critical, + _ => RiskLevel.low, + }; + } + + Future approve(String sessionId, String toolCallId) async { + await _sendDecision(sessionId, toolCallId, 'approved'); + await _persist(toolCallId, ApprovalDecision.approved); + _remove(toolCallId); + } + + Future reject(String sessionId, String toolCallId) async { + await _sendDecision(sessionId, toolCallId, 'rejected'); + await _persist(toolCallId, ApprovalDecision.rejected); + _remove(toolCallId); + } + + Future modify( + String sessionId, + String toolCallId, + Map modifications, + ) async { + final service = _ref.read(webSocketServiceProvider); + service.send(BridgeMessage.approvalResponse( + sessionId: sessionId, + toolCallId: toolCallId, + decision: 'modified', + modifications: modifications, + )); + await _persist(toolCallId, ApprovalDecision.modified, + modifications: jsonEncode(modifications)); + _remove(toolCallId); + } + + Future _sendDecision( + String sessionId, String toolCallId, String decision) async { + final service = _ref.read(webSocketServiceProvider); + service.send(BridgeMessage.approvalResponse( + sessionId: sessionId, + toolCallId: toolCallId, + decision: decision, + )); + } + + Future _persist( + String toolCallId, + ApprovalDecision decision, { + String? modifications, + }) async { + final db = _ref.read(databaseProvider); + final pending = state.where((t) => t.id == toolCallId).firstOrNull; + if (pending == null) return; + + await db.into(db.approvals).insertOnConflictUpdate( + ApprovalsCompanion( + id: Value(pending.id), + sessionId: Value(pending.sessionId), + tool: Value(pending.tool), + description: Value(pending.description ?? ''), + params: Value(jsonEncode(pending.params)), + reasoning: Value(pending.reasoning), + riskLevel: Value(pending.riskLevel.name), + decision: Value(decision.name), + modifications: Value(modifications), + createdAt: Value(pending.createdAt), + decidedAt: Value(DateTime.now()), + ), + ); + } + + void _remove(String toolCallId) { + state = state.where((t) => t.id != toolCallId).toList(); + } + + @override + void dispose() { + _sub?.cancel(); + super.dispose(); + } +} + +final pendingApprovalsProvider = + StateNotifierProvider>((ref) { + return PendingApprovalsNotifier(ref); +}); + +// --------------------------------------------------------------------------- +// Approval history (stream from DB) +// --------------------------------------------------------------------------- + +final approvalHistoryProvider = StreamProvider>((ref) { + final db = ref.watch(databaseProvider); + return db.select(db.approvals) + .watch() + .map((rows) => rows.map(_rowToToolCall).toList()); +}); + +ToolCall _rowToToolCall(dynamic row) { + Map params = {}; + try { + params = jsonDecode(row.params as String) as Map; + } catch (_) {} + + Map? result; + if (row.result != null) { + try { + result = jsonDecode(row.result as String) as Map; + } catch (_) {} + } + + return ToolCall( + id: row.id as String, + sessionId: row.sessionId as String, + tool: row.tool as String, + params: params, + description: row.description as String?, + reasoning: row.reasoning as String?, + riskLevel: _parseRiskLevel(row.riskLevel as String), + decision: _parseDecision(row.decision as String), + modifications: row.modifications as String?, + result: result, + createdAt: row.createdAt as DateTime, + decidedAt: row.decidedAt as DateTime?, + ); +} + +RiskLevel _parseRiskLevel(String v) { + return RiskLevel.values.firstWhere( + (e) => e.name == v, + orElse: () => RiskLevel.low, + ); +} + +ApprovalDecision _parseDecision(String v) { + return ApprovalDecision.values.firstWhere( + (e) => e.name == v, + orElse: () => ApprovalDecision.pending, + ); +} diff --git a/apps/mobile/lib/features/approvals/presentation/screens/approval_detail_screen.dart b/apps/mobile/lib/features/approvals/presentation/screens/approval_detail_screen.dart new file mode 100644 index 0000000..6d6018e --- /dev/null +++ b/apps/mobile/lib/features/approvals/presentation/screens/approval_detail_screen.dart @@ -0,0 +1,300 @@ +import 'dart:convert'; + +import 'package:flutter/material.dart'; +import 'package:flutter_riverpod/flutter_riverpod.dart'; +import 'package:go_router/go_router.dart'; + +import '../../../../core/models/message_models.dart'; +import '../../domain/providers/approval_provider.dart'; +import '../widgets/modification_editor.dart'; + +/// Full-screen detail view for a pending [ToolCall] approval. +/// +/// Route: `/approval/:id` +class ApprovalDetailScreen extends ConsumerStatefulWidget { + final String toolCallId; + + const ApprovalDetailScreen({super.key, required this.toolCallId}); + + @override + ConsumerState createState() => + _ApprovalDetailScreenState(); +} + +class _ApprovalDetailScreenState + extends ConsumerState { + final _modController = TextEditingController(); + bool _showModEditor = false; + + @override + void dispose() { + _modController.dispose(); + super.dispose(); + } + + ToolCall? _findToolCall(List list) { + try { + return list.firstWhere((t) => t.id == widget.toolCallId); + } catch (_) { + return null; + } + } + + Color _riskColor(RiskLevel level) { + return switch (level) { + RiskLevel.low => const Color(0xFF4CAF50), + RiskLevel.medium => const Color(0xFFFF9800), + RiskLevel.high => const Color(0xFFF44747), + RiskLevel.critical => const Color(0xFF8B0000), + }; + } + + void _approve(ToolCall toolCall) { + ref + .read(pendingApprovalsProvider.notifier) + .approve(toolCall.sessionId, toolCall.id); + context.pop(); + ScaffoldMessenger.of(context).showSnackBar( + const SnackBar(content: Text('Approved')), + ); + } + + void _reject(ToolCall toolCall) { + ref + .read(pendingApprovalsProvider.notifier) + .reject(toolCall.sessionId, toolCall.id); + context.pop(); + ScaffoldMessenger.of(context).showSnackBar( + const SnackBar(content: Text('Rejected')), + ); + } + + void _submitModifications(ToolCall toolCall) { + final text = _modController.text.trim(); + if (text.isEmpty) return; + ref.read(pendingApprovalsProvider.notifier).modify( + toolCall.sessionId, + toolCall.id, + {'instructions': text}, + ); + context.pop(); + ScaffoldMessenger.of(context).showSnackBar( + const SnackBar(content: Text('Modifications submitted')), + ); + } + + @override + Widget build(BuildContext context) { + final pending = ref.watch(pendingApprovalsProvider); + final toolCall = _findToolCall(pending); + + if (toolCall == null) { + return Scaffold( + appBar: AppBar(title: const Text('Approval')), + body: const Center(child: Text('Approval not found or already decided.')), + ); + } + + final riskColor = _riskColor(toolCall.riskLevel); + + return Scaffold( + appBar: AppBar(title: Text(toolCall.tool)), + body: ListView( + padding: const EdgeInsets.all(16), + children: [ + // Risk badge + description + Row( + children: [ + _RiskBadge(level: toolCall.riskLevel, color: riskColor), + const SizedBox(width: 12), + Expanded( + child: Text( + toolCall.description ?? 'No description provided.', + style: const TextStyle( + fontSize: 14, + color: Color(0xFFD4D4D4), + ), + ), + ), + ], + ), + const SizedBox(height: 16), + + // Parameters expandable card + _ExpandableSection( + title: 'Parameters', + child: Container( + width: double.infinity, + padding: const EdgeInsets.all(12), + decoration: BoxDecoration( + color: const Color(0xFF0D1117), + borderRadius: BorderRadius.circular(6), + ), + child: Text( + const JsonEncoder.withIndent(' ') + .convert(toolCall.params), + style: const TextStyle( + fontFamily: 'JetBrainsMono', + fontSize: 12, + color: Color(0xFFD4D4D4), + ), + ), + ), + ), + + // Reasoning expandable card (if available) + if (toolCall.reasoning != null) ...[ + const SizedBox(height: 8), + _ExpandableSection( + title: 'Reasoning', + child: Text( + toolCall.reasoning!, + style: const TextStyle( + fontSize: 13, + color: Color(0xFF9E9E9E), + ), + ), + ), + ], + + // Modification editor (shown after tapping Modify) + if (_showModEditor) ...[ + const SizedBox(height: 16), + ModificationEditor( + controller: _modController, + onSubmit: () => _submitModifications(toolCall), + ), + ], + + const SizedBox(height: 24), + + // Action buttons + Row( + children: [ + Expanded( + child: ElevatedButton( + onPressed: () => _approve(toolCall), + style: ElevatedButton.styleFrom( + backgroundColor: const Color(0xFF4CAF50), + foregroundColor: Colors.white, + padding: const EdgeInsets.symmetric(vertical: 12), + ), + child: const Text('Approve'), + ), + ), + const SizedBox(width: 8), + Expanded( + child: ElevatedButton( + onPressed: () => _reject(toolCall), + style: ElevatedButton.styleFrom( + backgroundColor: const Color(0xFFF44747), + foregroundColor: Colors.white, + padding: const EdgeInsets.symmetric(vertical: 12), + ), + child: const Text('Reject'), + ), + ), + const SizedBox(width: 8), + Expanded( + child: ElevatedButton( + onPressed: () => setState(() { + _showModEditor = !_showModEditor; + }), + style: ElevatedButton.styleFrom( + backgroundColor: const Color(0xFFFF9800), + foregroundColor: Colors.white, + padding: const EdgeInsets.symmetric(vertical: 12), + ), + child: const Text('Modify'), + ), + ), + ], + ), + ], + ), + ); + } +} + +class _RiskBadge extends StatelessWidget { + final RiskLevel level; + final Color color; + + const _RiskBadge({required this.level, required this.color}); + + @override + Widget build(BuildContext context) { + return Container( + padding: const EdgeInsets.symmetric(horizontal: 10, vertical: 5), + decoration: BoxDecoration( + color: color.withOpacity(0.15), + borderRadius: BorderRadius.circular(4), + border: Border.all(color: color.withOpacity(0.4)), + ), + child: Text( + level.name.toUpperCase(), + style: TextStyle( + fontSize: 11, + fontWeight: FontWeight.w700, + color: color, + ), + ), + ); + } +} + +class _ExpandableSection extends StatefulWidget { + final String title; + final Widget child; + + const _ExpandableSection({required this.title, required this.child}); + + @override + State<_ExpandableSection> createState() => _ExpandableSectionState(); +} + +class _ExpandableSectionState extends State<_ExpandableSection> { + bool _expanded = true; + + @override + Widget build(BuildContext context) { + return Card( + margin: EdgeInsets.zero, + child: Column( + children: [ + InkWell( + onTap: () => setState(() => _expanded = !_expanded), + child: Padding( + padding: + const EdgeInsets.symmetric(horizontal: 12, vertical: 10), + child: Row( + children: [ + Expanded( + child: Text( + widget.title, + style: const TextStyle( + fontSize: 13, + fontWeight: FontWeight.w600, + color: Color(0xFFD4D4D4), + ), + ), + ), + Icon( + _expanded ? Icons.expand_less : Icons.expand_more, + size: 18, + color: const Color(0xFF9E9E9E), + ), + ], + ), + ), + ), + if (_expanded) + Padding( + padding: const EdgeInsets.fromLTRB(12, 0, 12, 12), + child: widget.child, + ), + ], + ), + ); + } +} diff --git a/apps/mobile/lib/features/approvals/presentation/screens/approvals_screen.dart b/apps/mobile/lib/features/approvals/presentation/screens/approvals_screen.dart new file mode 100644 index 0000000..aad101d --- /dev/null +++ b/apps/mobile/lib/features/approvals/presentation/screens/approvals_screen.dart @@ -0,0 +1,181 @@ +import 'package:flutter/material.dart'; +import 'package:flutter_riverpod/flutter_riverpod.dart'; +import 'package:go_router/go_router.dart'; + +import '../../../../core/models/message_models.dart'; +import '../../domain/providers/approval_provider.dart'; +import '../widgets/approval_card.dart'; + +/// Two-tab screen: "Pending" approvals and "History" of past decisions. +class ApprovalsScreen extends ConsumerWidget { + const ApprovalsScreen({super.key}); + + @override + Widget build(BuildContext context, WidgetRef ref) { + return DefaultTabController( + length: 2, + child: Scaffold( + appBar: AppBar( + title: const Text('Approvals'), + bottom: const TabBar( + tabs: [ + Tab(text: 'Pending'), + Tab(text: 'History'), + ], + ), + ), + body: const TabBarView( + children: [ + _PendingTab(), + _HistoryTab(), + ], + ), + ), + ); + } +} + +// --------------------------------------------------------------------------- +// Pending tab +// --------------------------------------------------------------------------- + +class _PendingTab extends ConsumerWidget { + const _PendingTab(); + + @override + Widget build(BuildContext context, WidgetRef ref) { + final pending = ref.watch(pendingApprovalsProvider); + + if (pending.isEmpty) { + return const _EmptyState( + icon: Icons.check_circle_outline, + title: 'No pending approvals', + ); + } + + return ListView.builder( + padding: const EdgeInsets.symmetric(vertical: 8), + itemCount: pending.length, + itemBuilder: (context, index) { + final toolCall = pending[index]; + return ApprovalCard( + toolCall: toolCall, + onApprove: () => ref + .read(pendingApprovalsProvider.notifier) + .approve(toolCall.sessionId, toolCall.id), + onReject: () => ref + .read(pendingApprovalsProvider.notifier) + .reject(toolCall.sessionId, toolCall.id), + onTap: () => context.push('/approval/${toolCall.id}'), + ); + }, + ); + } +} + +// --------------------------------------------------------------------------- +// History tab +// --------------------------------------------------------------------------- + +class _HistoryTab extends ConsumerWidget { + const _HistoryTab(); + + Color _decisionColor(ApprovalDecision decision) { + return switch (decision) { + ApprovalDecision.approved => const Color(0xFF4CAF50), + ApprovalDecision.rejected => const Color(0xFFF44747), + ApprovalDecision.modified => const Color(0xFFFF9800), + ApprovalDecision.pending => const Color(0xFF569CD6), + }; + } + + @override + Widget build(BuildContext context, WidgetRef ref) { + final historyAsync = ref.watch(approvalHistoryProvider); + + return historyAsync.when( + loading: () => const Center(child: CircularProgressIndicator()), + error: (e, _) => Center(child: Text('Error: $e')), + data: (history) { + if (history.isEmpty) { + return const _EmptyState( + icon: Icons.history, + title: 'No history yet', + ); + } + + return ListView.builder( + padding: const EdgeInsets.symmetric(vertical: 8), + itemCount: history.length, + itemBuilder: (context, index) { + final item = history[index]; + final color = _decisionColor(item.decision); + return ListTile( + dense: true, + leading: const Icon(Icons.build_outlined, + size: 18, color: Color(0xFF9E9E9E)), + title: Text( + item.tool, + style: const TextStyle(fontSize: 13), + ), + subtitle: item.description != null + ? Text( + item.description!, + style: + const TextStyle(fontSize: 11, color: Color(0xFF9E9E9E)), + maxLines: 1, + overflow: TextOverflow.ellipsis, + ) + : null, + trailing: Container( + padding: + const EdgeInsets.symmetric(horizontal: 8, vertical: 3), + decoration: BoxDecoration( + color: color.withOpacity(0.15), + borderRadius: BorderRadius.circular(4), + border: Border.all(color: color.withOpacity(0.4)), + ), + child: Text( + item.decision.name.toUpperCase(), + style: TextStyle( + fontSize: 10, + fontWeight: FontWeight.w700, + color: color, + ), + ), + ), + ); + }, + ); + }, + ); + } +} + +// --------------------------------------------------------------------------- +// Empty state +// --------------------------------------------------------------------------- + +class _EmptyState extends StatelessWidget { + final IconData icon; + final String title; + + const _EmptyState({required this.icon, required this.title}); + + @override + Widget build(BuildContext context) { + return Center( + child: Column( + mainAxisSize: MainAxisSize.min, + children: [ + Icon(icon, size: 48, color: const Color(0xFF9E9E9E)), + const SizedBox(height: 12), + Text( + title, + style: const TextStyle(fontSize: 15, color: Color(0xFF9E9E9E)), + ), + ], + ), + ); + } +} diff --git a/apps/mobile/lib/features/approvals/presentation/widgets/approval_card.dart b/apps/mobile/lib/features/approvals/presentation/widgets/approval_card.dart new file mode 100644 index 0000000..954c946 --- /dev/null +++ b/apps/mobile/lib/features/approvals/presentation/widgets/approval_card.dart @@ -0,0 +1,156 @@ +import 'package:flutter/material.dart'; + +import '../../../../core/models/message_models.dart'; + +/// Card widget representing a pending tool-call approval. +class ApprovalCard extends StatelessWidget { + final ToolCall toolCall; + final VoidCallback onApprove; + final VoidCallback onReject; + final VoidCallback onTap; + + const ApprovalCard({ + super.key, + required this.toolCall, + required this.onApprove, + required this.onReject, + required this.onTap, + }); + + Color _riskColor(RiskLevel level) { + return switch (level) { + RiskLevel.low => const Color(0xFF4CAF50), + RiskLevel.medium => const Color(0xFFFF9800), + RiskLevel.high => const Color(0xFFF44747), + RiskLevel.critical => const Color(0xFF8B0000), + }; + } + + @override + Widget build(BuildContext context) { + final riskColor = _riskColor(toolCall.riskLevel); + + return Semantics( + label: 'Tool approval: ${toolCall.tool}, risk: ${toolCall.riskLevel.name}', + child: Card( + margin: const EdgeInsets.symmetric(horizontal: 12, vertical: 5), + child: InkWell( + onTap: onTap, + borderRadius: BorderRadius.circular(8), + child: Padding( + padding: const EdgeInsets.all(12), + child: Column( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + // Header row: tool icon + name + risk badge + Row( + children: [ + const Icon(Icons.build_outlined, + size: 16, color: Color(0xFF9E9E9E)), + const SizedBox(width: 6), + Expanded( + child: Text( + toolCall.tool, + style: const TextStyle( + fontSize: 14, + fontWeight: FontWeight.w600, + color: Color(0xFFD4D4D4), + ), + ), + ), + _RiskBadge(level: toolCall.riskLevel, color: riskColor), + ], + ), + if (toolCall.description != null) ...[ + const SizedBox(height: 6), + Text( + toolCall.description!, + style: const TextStyle( + fontSize: 12, + color: Color(0xFF9E9E9E), + ), + maxLines: 2, + overflow: TextOverflow.ellipsis, + ), + ], + const SizedBox(height: 10), + // Action buttons + Row( + children: [ + Expanded( + child: Semantics( + label: 'Approve tool call', + button: true, + child: OutlinedButton( + onPressed: onApprove, + style: OutlinedButton.styleFrom( + foregroundColor: const Color(0xFF4CAF50), + side: const BorderSide(color: Color(0xFF4CAF50)), + padding: const EdgeInsets.symmetric(vertical: 6), + ), + child: const Text('Approve', style: TextStyle(fontSize: 12)), + ), + ), + ), + const SizedBox(width: 8), + Expanded( + child: Semantics( + label: 'Reject tool call', + button: true, + child: OutlinedButton( + onPressed: onReject, + style: OutlinedButton.styleFrom( + foregroundColor: const Color(0xFFF44747), + side: const BorderSide(color: Color(0xFFF44747)), + padding: const EdgeInsets.symmetric(vertical: 6), + ), + child: const Text('Reject', style: TextStyle(fontSize: 12)), + ), + ), + ), + const SizedBox(width: 8), + OutlinedButton( + onPressed: onTap, + style: OutlinedButton.styleFrom( + padding: const EdgeInsets.symmetric( + horizontal: 12, vertical: 6), + ), + child: const Text('Details', style: TextStyle(fontSize: 12)), + ), + ], + ), + ], + ), + ), + ), + ), + ); + } +} + +class _RiskBadge extends StatelessWidget { + final RiskLevel level; + final Color color; + + const _RiskBadge({required this.level, required this.color}); + + @override + Widget build(BuildContext context) { + return Container( + padding: const EdgeInsets.symmetric(horizontal: 8, vertical: 3), + decoration: BoxDecoration( + color: color.withOpacity(0.15), + borderRadius: BorderRadius.circular(4), + border: Border.all(color: color.withOpacity(0.4)), + ), + child: Text( + level.name.toUpperCase(), + style: TextStyle( + fontSize: 10, + fontWeight: FontWeight.w700, + color: color, + ), + ), + ); + } +} diff --git a/apps/mobile/lib/features/approvals/presentation/widgets/modification_editor.dart b/apps/mobile/lib/features/approvals/presentation/widgets/modification_editor.dart new file mode 100644 index 0000000..1ca8347 --- /dev/null +++ b/apps/mobile/lib/features/approvals/presentation/widgets/modification_editor.dart @@ -0,0 +1,50 @@ +import 'package:flutter/material.dart'; + +/// A labeled text field + submit button used on the approval detail screen +/// when the user chooses to modify a tool call. +class ModificationEditor extends StatelessWidget { + final TextEditingController controller; + final VoidCallback onSubmit; + + const ModificationEditor({ + super.key, + required this.controller, + required this.onSubmit, + }); + + @override + Widget build(BuildContext context) { + return Column( + crossAxisAlignment: CrossAxisAlignment.stretch, + children: [ + const Text( + 'Modifications', + style: TextStyle( + fontSize: 12, + fontWeight: FontWeight.w600, + color: Color(0xFF9E9E9E), + letterSpacing: 0.5, + ), + ), + const SizedBox(height: 8), + TextField( + controller: controller, + minLines: 3, + maxLines: 6, + decoration: const InputDecoration( + hintText: 'Describe your modifications…', + ), + ), + const SizedBox(height: 8), + ElevatedButton( + onPressed: onSubmit, + style: ElevatedButton.styleFrom( + backgroundColor: const Color(0xFFFF9800), + foregroundColor: Colors.white, + ), + child: const Text('Submit Modifications'), + ), + ], + ); + } +} diff --git a/apps/mobile/lib/features/auth/presentation/screens/bridge_setup_screen.dart b/apps/mobile/lib/features/auth/presentation/screens/bridge_setup_screen.dart new file mode 100644 index 0000000..499f2c3 --- /dev/null +++ b/apps/mobile/lib/features/auth/presentation/screens/bridge_setup_screen.dart @@ -0,0 +1,224 @@ +import 'package:flutter/material.dart'; +import 'package:flutter_riverpod/flutter_riverpod.dart'; +import 'package:go_router/go_router.dart'; +import 'package:mobile_scanner/mobile_scanner.dart'; + +import '../../../../core/providers/bridge_provider.dart'; + +class BridgeSetupScreen extends ConsumerStatefulWidget { + const BridgeSetupScreen({super.key}); + + @override + ConsumerState createState() => _BridgeSetupScreenState(); +} + +class _BridgeSetupScreenState extends ConsumerState + with SingleTickerProviderStateMixin { + late TabController _tabController; + final _urlController = TextEditingController(); + final _tokenController = TextEditingController(); + bool _connecting = false; + String? _error; + bool _scanned = false; + + @override + void initState() { + super.initState(); + _tabController = TabController(length: 2, vsync: this); + } + + @override + void dispose() { + _tabController.dispose(); + _urlController.dispose(); + _tokenController.dispose(); + super.dispose(); + } + + void _onQrDetect(BarcodeCapture capture) { + if (_scanned) return; + final raw = capture.barcodes.firstOrNull?.rawValue; + if (raw == null) return; + // Expected format: recursor://connect?url=wss://...&token=... + final uri = Uri.tryParse(raw); + if (uri != null) { + final url = uri.queryParameters['url'] ?? ''; + final token = uri.queryParameters['token'] ?? ''; + if (url.isNotEmpty) { + setState(() { + _scanned = true; + _urlController.text = url; + _tokenController.text = token; + }); + _tabController.animateTo(1); + } + } + } + + Future _connect() async { + final url = _urlController.text.trim(); + final token = _tokenController.text.trim(); + if (url.isEmpty) { + setState(() => _error = 'Bridge URL is required'); + return; + } + setState(() { + _connecting = true; + _error = null; + }); + try { + await ref.read(bridgeProvider.notifier).connect(url, token); + if (mounted) context.go('/home/chat'); + } catch (e) { + setState(() => _error = e.toString()); + } finally { + if (mounted) setState(() => _connecting = false); + } + } + + @override + Widget build(BuildContext context) { + return Scaffold( + backgroundColor: const Color(0xFF1E1E1E), + appBar: AppBar( + backgroundColor: const Color(0xFF252526), + title: const Text('Connect Bridge'), + bottom: TabBar( + controller: _tabController, + indicatorColor: const Color(0xFF569CD6), + labelColor: const Color(0xFF569CD6), + unselectedLabelColor: Colors.grey, + tabs: const [ + Tab(icon: Icon(Icons.qr_code_scanner), text: 'QR Scanner'), + Tab(icon: Icon(Icons.edit), text: 'Manual Entry'), + ], + ), + ), + body: TabBarView( + controller: _tabController, + children: [ + _QrTab(onDetect: _onQrDetect), + _ManualTab( + urlController: _urlController, + tokenController: _tokenController, + connecting: _connecting, + error: _error, + onConnect: _connect, + ), + ], + ), + ); + } +} + +class _QrTab extends StatelessWidget { + final void Function(BarcodeCapture) onDetect; + const _QrTab({required this.onDetect}); + + @override + Widget build(BuildContext context) { + return Column( + children: [ + Expanded( + child: ClipRRect( + borderRadius: BorderRadius.circular(12), + child: MobileScanner(onDetect: onDetect), + ), + ), + const Padding( + padding: EdgeInsets.all(16), + child: Text( + 'Point the camera at the QR code shown in your bridge server', + textAlign: TextAlign.center, + style: TextStyle(color: Color(0xFF9CDCFE)), + ), + ), + ], + ); + } +} + +class _ManualTab extends StatelessWidget { + final TextEditingController urlController; + final TextEditingController tokenController; + final bool connecting; + final String? error; + final VoidCallback onConnect; + + const _ManualTab({ + required this.urlController, + required this.tokenController, + required this.connecting, + required this.error, + required this.onConnect, + }); + + @override + Widget build(BuildContext context) { + const inputDecoration = InputDecoration( + filled: true, + fillColor: Color(0xFF252526), + border: OutlineInputBorder( + borderRadius: BorderRadius.all(Radius.circular(8)), + borderSide: BorderSide.none, + ), + labelStyle: TextStyle(color: Color(0xFF9CDCFE)), + ); + + return SingleChildScrollView( + padding: const EdgeInsets.all(24), + child: Column( + crossAxisAlignment: CrossAxisAlignment.stretch, + children: [ + TextField( + controller: urlController, + style: const TextStyle(color: Colors.white), + decoration: inputDecoration.copyWith( + labelText: 'Bridge URL (wss://...)', + hintText: 'wss://192.168.1.100:8080', + hintStyle: const TextStyle(color: Colors.grey), + ), + ), + const SizedBox(height: 16), + TextField( + controller: tokenController, + obscureText: true, + style: const TextStyle(color: Colors.white), + decoration: + inputDecoration.copyWith(labelText: 'Auth Token (optional)'), + ), + const SizedBox(height: 24), + if (error != null) + Padding( + padding: const EdgeInsets.only(bottom: 12), + child: Text( + error!, + style: const TextStyle(color: Colors.redAccent), + textAlign: TextAlign.center, + ), + ), + FilledButton( + onPressed: connecting ? null : onConnect, + style: FilledButton.styleFrom( + backgroundColor: const Color(0xFF569CD6), + padding: const EdgeInsets.symmetric(vertical: 16), + shape: RoundedRectangleBorder( + borderRadius: BorderRadius.circular(8), + ), + ), + child: connecting + ? const SizedBox( + height: 20, + width: 20, + child: CircularProgressIndicator( + strokeWidth: 2, + color: Colors.white, + ), + ) + : const Text('Connect', style: TextStyle(fontSize: 16)), + ), + ], + ), + ); + } +} diff --git a/apps/mobile/lib/features/auth/presentation/screens/login_screen.dart b/apps/mobile/lib/features/auth/presentation/screens/login_screen.dart new file mode 100644 index 0000000..06281ea --- /dev/null +++ b/apps/mobile/lib/features/auth/presentation/screens/login_screen.dart @@ -0,0 +1,151 @@ +import 'package:flutter/material.dart'; +import 'package:flutter_riverpod/flutter_riverpod.dart'; +import 'package:go_router/go_router.dart'; + +import '../../../../core/providers/auth_provider.dart'; +import '../../../../core/auth/auth_state.dart'; +import '../widgets/auth_button.dart'; + +class LoginScreen extends ConsumerStatefulWidget { + const LoginScreen({super.key}); + + @override + ConsumerState createState() => _LoginScreenState(); +} + +class _LoginScreenState extends ConsumerState { + final _patController = TextEditingController(); + bool _showPat = false; + bool _patMode = false; + + @override + void dispose() { + _patController.dispose(); + super.dispose(); + } + + Future _signInWithGithub() async { + // OAuth flow: start flow to get auth URL, then exchange code. + // For now sign in with empty code to trigger the OAuth redirect flow. + await ref.read(authStateProvider.notifier).signInWithOAuth(''); + } + + Future _signInWithPat() async { + final pat = _patController.text.trim(); + if (pat.isEmpty) return; + await ref.read(authStateProvider.notifier).signInWithPAT(pat); + } + + @override + Widget build(BuildContext context) { + final authState = ref.watch(authStateProvider); + + ref.listen(authStateProvider, (_, next) { + if (next.status == AuthStatus.authenticated && context.mounted) { + context.go('/home'); + } + }); + + final isLoading = authState.status == AuthStatus.loading; + + return Scaffold( + backgroundColor: const Color(0xFF1E1E1E), + body: SafeArea( + child: Padding( + padding: const EdgeInsets.symmetric(horizontal: 32), + child: Column( + mainAxisAlignment: MainAxisAlignment.center, + crossAxisAlignment: CrossAxisAlignment.stretch, + children: [ + Image.asset( + 'assets/branding/ReCursor_Darklogo.png', + height: 80, + fit: BoxFit.contain, + ), + const SizedBox(height: 48), + const Text( + 'Welcome to ReCursor', + textAlign: TextAlign.center, + style: TextStyle( + color: Colors.white, + fontSize: 24, + fontWeight: FontWeight.bold, + ), + ), + const SizedBox(height: 8), + const Text( + 'Sign in to connect your AI coding agents', + textAlign: TextAlign.center, + style: TextStyle(color: Color(0xFF9CDCFE), fontSize: 14), + ), + const SizedBox(height: 40), + if (!_patMode) ...[ + AuthButton( + label: 'Sign in with GitHub', + icon: Icons.code, + onPressed: isLoading ? null : _signInWithGithub, + isLoading: isLoading, + ), + const SizedBox(height: 16), + TextButton( + onPressed: () => setState(() => _patMode = true), + child: const Text( + 'Use Personal Access Token', + style: TextStyle(color: Color(0xFF4EC9B0)), + ), + ), + ] else ...[ + TextField( + controller: _patController, + obscureText: !_showPat, + style: const TextStyle(color: Colors.white), + decoration: InputDecoration( + labelText: 'Personal Access Token', + labelStyle: const TextStyle(color: Color(0xFF9CDCFE)), + filled: true, + fillColor: const Color(0xFF252526), + border: OutlineInputBorder( + borderRadius: BorderRadius.circular(8), + borderSide: BorderSide.none, + ), + suffixIcon: IconButton( + icon: Icon( + _showPat ? Icons.visibility_off : Icons.visibility, + color: const Color(0xFF9CDCFE), + ), + onPressed: () => setState(() => _showPat = !_showPat), + ), + ), + ), + const SizedBox(height: 16), + AuthButton( + label: 'Sign In', + icon: Icons.login, + onPressed: isLoading ? null : _signInWithPat, + isLoading: isLoading, + ), + const SizedBox(height: 8), + TextButton( + onPressed: () => setState(() => _patMode = false), + child: const Text( + 'Back', + style: TextStyle(color: Color(0xFF9CDCFE)), + ), + ), + ], + if (authState.status == AuthStatus.error) + Padding( + padding: const EdgeInsets.only(top: 16), + child: Text( + authState.errorMessage ?? 'An error occurred', + textAlign: TextAlign.center, + style: const TextStyle(color: Colors.redAccent), + ), + ), + ], + ), + ), + ), + ); + } +} diff --git a/apps/mobile/lib/features/auth/presentation/screens/splash_screen.dart b/apps/mobile/lib/features/auth/presentation/screens/splash_screen.dart new file mode 100644 index 0000000..63f702f --- /dev/null +++ b/apps/mobile/lib/features/auth/presentation/screens/splash_screen.dart @@ -0,0 +1,65 @@ +import 'package:flutter/material.dart'; +import 'package:flutter_riverpod/flutter_riverpod.dart'; +import 'package:go_router/go_router.dart'; + +import '../../../../core/providers/auth_provider.dart'; +import '../../../../core/auth/auth_state.dart'; + +class SplashScreen extends ConsumerStatefulWidget { + const SplashScreen({super.key}); + + @override + ConsumerState createState() => _SplashScreenState(); +} + +class _SplashScreenState extends ConsumerState + with SingleTickerProviderStateMixin { + late AnimationController _controller; + late Animation _opacity; + + @override + void initState() { + super.initState(); + _controller = AnimationController( + vsync: this, + duration: const Duration(milliseconds: 900), + ); + _opacity = CurvedAnimation(parent: _controller, curve: Curves.easeIn); + _controller.forward(); + _checkAuth(); + } + + Future _checkAuth() async { + await Future.delayed(const Duration(milliseconds: 1200)); + if (!mounted) return; + final authState = ref.read(authStateProvider); + if (authState.status == AuthStatus.authenticated) { + context.go('/home'); + } else { + context.go('/login'); + } + } + + @override + void dispose() { + _controller.dispose(); + super.dispose(); + } + + @override + Widget build(BuildContext context) { + return Scaffold( + backgroundColor: const Color(0xFF1E1E1E), + body: Center( + child: FadeTransition( + opacity: _opacity, + child: Image.asset( + 'assets/branding/ReCursor_Darklogo.png', + width: 200, + fit: BoxFit.contain, + ), + ), + ), + ); + } +} diff --git a/apps/mobile/lib/features/auth/presentation/widgets/auth_button.dart b/apps/mobile/lib/features/auth/presentation/widgets/auth_button.dart new file mode 100644 index 0000000..16f940a --- /dev/null +++ b/apps/mobile/lib/features/auth/presentation/widgets/auth_button.dart @@ -0,0 +1,73 @@ +import 'package:flutter/material.dart'; + +class AuthButton extends StatelessWidget { + final String label; + final IconData icon; + final VoidCallback? onPressed; + final bool isLoading; + + const AuthButton({ + super.key, + required this.label, + required this.icon, + this.onPressed, + this.isLoading = false, + }); + + @override + Widget build(BuildContext context) { + return DecoratedBox( + decoration: BoxDecoration( + gradient: const LinearGradient( + colors: [Color(0xFF569CD6), Color(0xFF4EC9B0)], + begin: Alignment.centerLeft, + end: Alignment.centerRight, + ), + borderRadius: BorderRadius.circular(8), + boxShadow: [ + BoxShadow( + color: const Color(0xFF569CD6).withOpacity(0.3), + blurRadius: 8, + offset: const Offset(0, 4), + ), + ], + ), + child: Material( + color: Colors.transparent, + child: InkWell( + onTap: onPressed, + borderRadius: BorderRadius.circular(8), + child: Padding( + padding: const EdgeInsets.symmetric(vertical: 16, horizontal: 24), + child: Row( + mainAxisAlignment: MainAxisAlignment.center, + children: [ + if (isLoading) + const SizedBox( + height: 20, + width: 20, + child: CircularProgressIndicator( + strokeWidth: 2, + color: Colors.white, + ), + ) + else ...[ + Icon(icon, color: Colors.white, size: 20), + const SizedBox(width: 12), + Text( + label, + style: const TextStyle( + color: Colors.white, + fontSize: 16, + fontWeight: FontWeight.w600, + ), + ), + ], + ], + ), + ), + ), + ), + ); + } +} diff --git a/apps/mobile/lib/features/chat/domain/providers/chat_provider.dart b/apps/mobile/lib/features/chat/domain/providers/chat_provider.dart new file mode 100644 index 0000000..8870965 --- /dev/null +++ b/apps/mobile/lib/features/chat/domain/providers/chat_provider.dart @@ -0,0 +1,262 @@ +import 'dart:convert'; + +import 'package:drift/drift.dart' show Value; +import 'package:flutter_riverpod/flutter_riverpod.dart'; +import 'package:riverpod_annotation/riverpod_annotation.dart'; +import 'package:uuid/uuid.dart'; + +import '../../../../core/models/message_models.dart'; +import '../../../../core/models/session_models.dart'; +import '../../../../core/providers/database_provider.dart'; +import '../../../../core/network/bridge_socket.dart'; +import '../../../../core/storage/database.dart' as db_lib; + +part 'chat_provider.g.dart'; + +const _uuid = Uuid(); + +// --------------------------------------------------------------------------- +// Streaming message buffer: sessionId → current streaming text +// --------------------------------------------------------------------------- + +final streamingMessageProvider = + StateProvider>((ref) => {}); + +// --------------------------------------------------------------------------- +// Messages stream for a session +// --------------------------------------------------------------------------- + +@riverpod +Stream> messages(Ref ref, String sessionId) { + final db = ref.watch(databaseProvider); + return db.messageDao.watchMessagesForSession(sessionId).map( + (rows) => rows.map(_rowToDomainMessage).toList(), + ); +} + +Message _rowToDomainMessage(db_lib.Message row) { + List parts = []; + if (row.metadata != null) { + try { + final decoded = jsonDecode(row.metadata!) as Map; + final partsJson = decoded['parts'] as List?; + if (partsJson != null) { + parts = partsJson + .map((p) => MessagePart.fromJson(p as Map)) + .toList(); + } + } catch (_) {} + } + final role = MessageRole.values.firstWhere( + (e) => e.name == row.role, + orElse: () => MessageRole.agent, + ); + final type = MessageType.values.firstWhere( + (e) => e.name == row.messageType, + orElse: () => MessageType.text, + ); + return Message( + id: row.id, + sessionId: row.sessionId, + role: role, + content: row.content, + type: type, + parts: parts, + createdAt: row.createdAt, + updatedAt: row.updatedAt, + synced: row.synced, + ); +} + +// --------------------------------------------------------------------------- +// Chat notifier +// --------------------------------------------------------------------------- + +@riverpod +class ChatNotifier extends _$ChatNotifier { + @override + Future build() async { + final socket = ref.watch(bridgeSocketProvider); + socket.messageStream.listen(_handleBridgeMessage); + } + + void _handleBridgeMessage(Map msg) { + final type = msg['type'] as String?; + final sessionId = msg['session_id'] as String? ?? ''; + + switch (type) { + case 'stream_start': + _setStreaming(sessionId, ''); + case 'stream_chunk': + final chunk = msg['chunk'] as String? ?? ''; + _appendStreaming(sessionId, chunk); + case 'stream_end': + _finalizeStreaming(sessionId); + case 'tool_call': + _persistToolCall(sessionId, msg); + case 'tool_result': + _persistToolResult(sessionId, msg); + case 'session_ready': + _onSessionReady(sessionId, msg); + default: + break; + } + } + + void _setStreaming(String sessionId, String text) { + final current = Map.from( + ref.read(streamingMessageProvider), + ); + current[sessionId] = text; + ref.read(streamingMessageProvider.notifier).state = current; + } + + void _appendStreaming(String sessionId, String chunk) { + final current = Map.from( + ref.read(streamingMessageProvider), + ); + current[sessionId] = (current[sessionId] ?? '') + chunk; + ref.read(streamingMessageProvider.notifier).state = current; + } + + Future _finalizeStreaming(String sessionId) async { + final current = Map.from( + ref.read(streamingMessageProvider), + ); + final text = current.remove(sessionId) ?? ''; + ref.read(streamingMessageProvider.notifier).state = current; + + if (text.isNotEmpty) { + final db = ref.read(databaseProvider); + final now = DateTime.now(); + await db.messageDao.insertMessage(_toCompanion(Message( + id: _uuid.v4(), + sessionId: sessionId, + role: MessageRole.agent, + content: text, + type: MessageType.text, + parts: [MessagePart.text(content: text)], + createdAt: now, + updatedAt: now, + ))); + } + } + + Future _persistToolCall( + String sessionId, Map msg) async { + final db = ref.read(databaseProvider); + final toolName = msg['tool'] as String? ?? 'unknown'; + final params = + (msg['params'] as Map?) ?? {}; + final id = msg['id'] as String? ?? _uuid.v4(); + final now = DateTime.now(); + + await db.messageDao.insertMessage(_toCompanion(Message( + id: _uuid.v4(), + sessionId: sessionId, + role: MessageRole.agent, + content: '', + type: MessageType.toolCall, + parts: [MessagePart.toolUse(tool: toolName, params: params, id: id)], + createdAt: now, + updatedAt: now, + ))); + } + + Future _persistToolResult( + String sessionId, Map msg) async { + final db = ref.read(databaseProvider); + final toolCallId = msg['tool_call_id'] as String? ?? ''; + final success = msg['success'] as bool? ?? true; + final content = msg['content'] as String? ?? ''; + final now = DateTime.now(); + + await db.messageDao.insertMessage(_toCompanion(Message( + id: _uuid.v4(), + sessionId: sessionId, + role: MessageRole.agent, + content: '', + type: MessageType.toolResult, + parts: [ + MessagePart.toolResult( + toolCallId: toolCallId, + result: ToolResult(success: success, content: content), + ) + ], + createdAt: now, + updatedAt: now, + ))); + } + + void _onSessionReady(String sessionId, Map msg) { + // Session is live; any UI waiting can react via activeSessionsProvider + } + + // ---------- Public actions ----------------------------------------------- + + Future sendMessage(String sessionId, String content) async { + if (content.trim().isEmpty) return; + final db = ref.read(databaseProvider); + + // Optimistic insert + final now = DateTime.now(); + final msg = Message( + id: _uuid.v4(), + sessionId: sessionId, + role: MessageRole.user, + content: content, + type: MessageType.text, + parts: [MessagePart.text(content: content)], + createdAt: now, + updatedAt: now, + synced: false, + ); + await db.messageDao.insertMessage(_toCompanion(msg)); + + // Send over socket + final socket = ref.read(bridgeSocketProvider); + socket.send({ + 'type': 'user_message', + 'session_id': sessionId, + 'content': content, + }); + } + + Future startSession(String agentId, String workingDir) async { + final socket = ref.read(bridgeSocketProvider); + final sessionId = _uuid.v4(); + socket.send({ + 'type': 'session_start', + 'session_id': sessionId, + 'agent_id': agentId, + 'working_directory': workingDir, + }); + } + + Future endSession(String sessionId) async { + final socket = ref.read(bridgeSocketProvider); + socket.send({'type': 'session_end', 'session_id': sessionId}); + } +} + +// --------------------------------------------------------------------------- +// Helpers +// --------------------------------------------------------------------------- + +db_lib.MessagesCompanion _toCompanion(Message msg) { + final metadata = jsonEncode({ + 'parts': msg.parts.map((p) => p.toJson()).toList(), + if (msg.metadata != null) ...msg.metadata!, + }); + return db_lib.MessagesCompanion( + id: Value(msg.id), + sessionId: Value(msg.sessionId), + role: Value(msg.role.name), + content: Value(msg.content), + messageType: Value(msg.type.name), + metadata: Value(metadata), + createdAt: Value(msg.createdAt), + updatedAt: Value(msg.updatedAt ?? msg.createdAt), + synced: Value(msg.synced), + ); +} diff --git a/apps/mobile/lib/features/chat/domain/providers/chat_provider.g.dart b/apps/mobile/lib/features/chat/domain/providers/chat_provider.g.dart new file mode 100644 index 0000000..ab9de01 --- /dev/null +++ b/apps/mobile/lib/features/chat/domain/providers/chat_provider.g.dart @@ -0,0 +1,175 @@ +// GENERATED CODE - DO NOT MODIFY BY HAND + +part of 'chat_provider.dart'; + +// ************************************************************************** +// RiverpodGenerator +// ************************************************************************** + +String _$messagesHash() => r'df25cd2487c082acbc3600ec8bc8a1448f4b96b0'; + +/// Copied from Dart SDK +class _SystemHash { + _SystemHash._(); + + static int combine(int hash, int value) { + // ignore: parameter_assignments + hash = 0x1fffffff & (hash + value); + // ignore: parameter_assignments + hash = 0x1fffffff & (hash + ((0x0007ffff & hash) << 10)); + return hash ^ (hash >> 6); + } + + static int finish(int hash) { + // ignore: parameter_assignments + hash = 0x1fffffff & (hash + ((0x03ffffff & hash) << 3)); + // ignore: parameter_assignments + hash = hash ^ (hash >> 11); + return 0x1fffffff & (hash + ((0x00003fff & hash) << 15)); + } +} + +/// See also [messages]. +@ProviderFor(messages) +const messagesProvider = MessagesFamily(); + +/// See also [messages]. +class MessagesFamily extends Family>> { + /// See also [messages]. + const MessagesFamily(); + + /// See also [messages]. + MessagesProvider call( + String sessionId, + ) { + return MessagesProvider( + sessionId, + ); + } + + @override + MessagesProvider getProviderOverride( + covariant MessagesProvider provider, + ) { + return call( + provider.sessionId, + ); + } + + static const Iterable? _dependencies = null; + + @override + Iterable? get dependencies => _dependencies; + + static const Iterable? _allTransitiveDependencies = null; + + @override + Iterable? get allTransitiveDependencies => + _allTransitiveDependencies; + + @override + String? get name => r'messagesProvider'; +} + +/// See also [messages]. +class MessagesProvider extends AutoDisposeStreamProvider> { + /// See also [messages]. + MessagesProvider( + String sessionId, + ) : this._internal( + (ref) => messages( + ref as MessagesRef, + sessionId, + ), + from: messagesProvider, + name: r'messagesProvider', + debugGetCreateSourceHash: + const bool.fromEnvironment('dart.vm.product') + ? null + : _$messagesHash, + dependencies: MessagesFamily._dependencies, + allTransitiveDependencies: MessagesFamily._allTransitiveDependencies, + sessionId: sessionId, + ); + + MessagesProvider._internal( + super._createNotifier, { + required super.name, + required super.dependencies, + required super.allTransitiveDependencies, + required super.debugGetCreateSourceHash, + required super.from, + required this.sessionId, + }) : super.internal(); + + final String sessionId; + + @override + Override overrideWith( + Stream> Function(MessagesRef provider) create, + ) { + return ProviderOverride( + origin: this, + override: MessagesProvider._internal( + (ref) => create(ref as MessagesRef), + from: from, + name: null, + dependencies: null, + allTransitiveDependencies: null, + debugGetCreateSourceHash: null, + sessionId: sessionId, + ), + ); + } + + @override + AutoDisposeStreamProviderElement> createElement() { + return _MessagesProviderElement(this); + } + + @override + bool operator ==(Object other) { + return other is MessagesProvider && other.sessionId == sessionId; + } + + @override + int get hashCode { + var hash = _SystemHash.combine(0, runtimeType.hashCode); + hash = _SystemHash.combine(hash, sessionId.hashCode); + + return _SystemHash.finish(hash); + } +} + +@Deprecated('Will be removed in 3.0. Use Ref instead') +// ignore: unused_element +mixin MessagesRef on AutoDisposeStreamProviderRef> { + /// The parameter `sessionId` of this provider. + String get sessionId; +} + +class _MessagesProviderElement + extends AutoDisposeStreamProviderElement> with MessagesRef { + _MessagesProviderElement(super.provider); + + @override + String get sessionId => (origin as MessagesProvider).sessionId; +} + +String _$chatNotifierHash() => r'eed2e0994577ffb39e68f70ea55e381e3e24fd2a'; + +/// See also [ChatNotifier]. +@ProviderFor(ChatNotifier) +final chatNotifierProvider = + AutoDisposeAsyncNotifierProvider.internal( + ChatNotifier.new, + name: r'chatNotifierProvider', + debugGetCreateSourceHash: + const bool.fromEnvironment('dart.vm.product') ? null : _$chatNotifierHash, + dependencies: null, + allTransitiveDependencies: null, +); + +typedef _$ChatNotifier = AutoDisposeAsyncNotifier; +// ignore_for_file: type=lint +// ignore_for_file: subtype_of_sealed_class, invalid_use_of_internal_member, invalid_use_of_visible_for_testing_member, deprecated_member_use_from_same_package diff --git a/apps/mobile/lib/features/chat/domain/providers/session_provider.dart b/apps/mobile/lib/features/chat/domain/providers/session_provider.dart new file mode 100644 index 0000000..4430715 --- /dev/null +++ b/apps/mobile/lib/features/chat/domain/providers/session_provider.dart @@ -0,0 +1,86 @@ +import 'package:flutter_riverpod/flutter_riverpod.dart'; +import 'package:riverpod_annotation/riverpod_annotation.dart'; + +import '../../../../core/models/session_models.dart'; +import '../../../../core/providers/database_provider.dart'; +import '../../../../core/network/bridge_socket.dart'; +import '../../../../core/storage/database.dart' as db_lib; + +part 'session_provider.g.dart'; + +// --------------------------------------------------------------------------- +// Current session ID +// --------------------------------------------------------------------------- + +final currentSessionProvider = StateProvider((ref) => null); + +// --------------------------------------------------------------------------- +// Active sessions list +// --------------------------------------------------------------------------- + +@riverpod +class ActiveSessions extends _$ActiveSessions { + @override + Future> build() async { + final db = ref.watch(databaseProvider); + final rows = await db.sessionDao.watchAllSessions().first; + final sessions = rows.map(_rowToChatSession).toList(); + + // Keep up-to-date when bridge sends session events + final socket = ref.watch(bridgeSocketProvider); + socket.messageStream.listen((msg) { + if (msg['type'] == 'session_ready' || msg['type'] == 'session_closed') { + ref.invalidateSelf(); + } + }); + + return sessions; + } + + Future refresh() async { + ref.invalidateSelf(); + } + + Future deleteSession(String sessionId) async { + final db = ref.read(databaseProvider); + await db.sessionDao.deleteSession(sessionId); + ref.invalidateSelf(); + } +} + +// --------------------------------------------------------------------------- +// Single session selector +// --------------------------------------------------------------------------- + +final activeSessionProvider = + Provider.family((ref, sessionId) { + final sessions = ref.watch(activeSessionsProvider).valueOrNull ?? []; + try { + return sessions.firstWhere((s) => s.id == sessionId); + } catch (_) { + return null; + } +}); + +// --------------------------------------------------------------------------- +// Helpers +// --------------------------------------------------------------------------- + +ChatSession _rowToChatSession(db_lib.Session row) { + return ChatSession( + id: row.id, + agentType: row.agentType, + agentId: row.agentId, + title: row.title, + workingDirectory: row.workingDirectory, + branch: row.branch, + status: SessionStatus.values.firstWhere( + (e) => e.name == row.status, + orElse: () => SessionStatus.active, + ), + createdAt: row.createdAt, + lastMessageAt: row.lastMessageAt, + updatedAt: row.updatedAt, + synced: row.synced, + ); +} diff --git a/apps/mobile/lib/features/chat/domain/providers/session_provider.g.dart b/apps/mobile/lib/features/chat/domain/providers/session_provider.g.dart new file mode 100644 index 0000000..1f94b04 --- /dev/null +++ b/apps/mobile/lib/features/chat/domain/providers/session_provider.g.dart @@ -0,0 +1,26 @@ +// GENERATED CODE - DO NOT MODIFY BY HAND + +part of 'session_provider.dart'; + +// ************************************************************************** +// RiverpodGenerator +// ************************************************************************** + +String _$activeSessionsHash() => r'83c85f93dece06f6d4a19b8d7a9cbf1ca8d27bdc'; + +/// See also [ActiveSessions]. +@ProviderFor(ActiveSessions) +final activeSessionsProvider = AutoDisposeAsyncNotifierProvider>.internal( + ActiveSessions.new, + name: r'activeSessionsProvider', + debugGetCreateSourceHash: const bool.fromEnvironment('dart.vm.product') + ? null + : _$activeSessionsHash, + dependencies: null, + allTransitiveDependencies: null, +); + +typedef _$ActiveSessions = AutoDisposeAsyncNotifier>; +// ignore_for_file: type=lint +// ignore_for_file: subtype_of_sealed_class, invalid_use_of_internal_member, invalid_use_of_visible_for_testing_member, deprecated_member_use_from_same_package diff --git a/apps/mobile/lib/features/chat/presentation/screens/chat_screen.dart b/apps/mobile/lib/features/chat/presentation/screens/chat_screen.dart new file mode 100644 index 0000000..bb5e77e --- /dev/null +++ b/apps/mobile/lib/features/chat/presentation/screens/chat_screen.dart @@ -0,0 +1,219 @@ +import 'package:flutter/material.dart'; +import 'package:flutter_riverpod/flutter_riverpod.dart'; + +import '../../../../core/models/message_models.dart'; +import '../../domain/providers/chat_provider.dart'; +import '../../domain/providers/session_provider.dart'; +import '../widgets/chat_input_bar.dart'; +import '../widgets/message_bubble.dart'; +import '../widgets/voice_input_sheet.dart'; +import 'session_list_screen.dart'; + +class ChatScreen extends ConsumerStatefulWidget { + final String sessionId; + const ChatScreen({super.key, required this.sessionId}); + + @override + ConsumerState createState() => _ChatScreenState(); +} + +class _ChatScreenState extends ConsumerState { + final _scrollController = ScrollController(); + + @override + void dispose() { + _scrollController.dispose(); + super.dispose(); + } + + void _scrollToBottom() { + WidgetsBinding.instance.addPostFrameCallback((_) { + if (_scrollController.hasClients) { + _scrollController.animateTo( + _scrollController.position.maxScrollExtent, + duration: const Duration(milliseconds: 200), + curve: Curves.easeOut, + ); + } + }); + } + + void _sendMessage(String text) { + ref.read(chatNotifierProvider.notifier).sendMessage(widget.sessionId, text); + _scrollToBottom(); + } + + void _openVoice() { + showModalBottomSheet( + context: context, + isScrollControlled: true, + backgroundColor: Colors.transparent, + builder: (_) => VoiceInputSheet( + onSend: (text) { + Navigator.pop(context); + _sendMessage(text); + }, + ), + ); + } + + @override + Widget build(BuildContext context) { + final session = ref.watch(activeSessionProvider(widget.sessionId)); + final messagesAsync = ref.watch(messagesProvider(widget.sessionId)); + final streamingMap = ref.watch(streamingMessageProvider); + final streamingText = streamingMap[widget.sessionId]; + + // Auto-scroll when messages change + ref.listen(messagesProvider(widget.sessionId), (_, __) => _scrollToBottom()); + + return LayoutBuilder( + builder: (context, constraints) { + final isTablet = constraints.maxWidth >= 720; + + if (isTablet) { + return Row( + children: [ + SizedBox( + width: 300, + child: const SessionListScreen(), + ), + const VerticalDivider(width: 1, color: Color(0xFF3C3C3C)), + Expanded(child: _ChatBody( + sessionId: widget.sessionId, + sessionTitle: session?.title ?? 'Chat', + branch: session?.branch, + messagesAsync: messagesAsync, + streamingText: streamingText, + scrollController: _scrollController, + onSend: _sendMessage, + onVoice: _openVoice, + )), + ], + ); + } + + return _ChatBody( + sessionId: widget.sessionId, + sessionTitle: session?.title ?? 'Chat', + branch: session?.branch, + messagesAsync: messagesAsync, + streamingText: streamingText, + scrollController: _scrollController, + onSend: _sendMessage, + onVoice: _openVoice, + ); + }, + ); + } +} + +class _ChatBody extends StatelessWidget { + final String sessionId; + final String sessionTitle; + final String? branch; + final AsyncValue> messagesAsync; + final String? streamingText; + final ScrollController scrollController; + final void Function(String) onSend; + final VoidCallback onVoice; + + const _ChatBody({ + required this.sessionId, + required this.sessionTitle, + required this.branch, + required this.messagesAsync, + required this.streamingText, + required this.scrollController, + required this.onSend, + required this.onVoice, + }); + + @override + Widget build(BuildContext context) { + return Scaffold( + backgroundColor: const Color(0xFF1E1E1E), + appBar: AppBar( + backgroundColor: const Color(0xFF252526), + title: Row( + children: [ + Expanded( + child: Text( + sessionTitle, + overflow: TextOverflow.ellipsis, + style: const TextStyle(color: Colors.white), + ), + ), + if (branch != null) + Container( + margin: const EdgeInsets.only(left: 8), + padding: const EdgeInsets.symmetric(horizontal: 8, vertical: 2), + decoration: BoxDecoration( + color: const Color(0xFF3C3C3C), + borderRadius: BorderRadius.circular(12), + ), + child: Row( + mainAxisSize: MainAxisSize.min, + children: [ + const Icon(Icons.call_split, size: 12, color: Color(0xFF4EC9B0)), + const SizedBox(width: 4), + Text( + branch!, + style: const TextStyle( + color: Color(0xFF4EC9B0), fontSize: 12), + ), + ], + ), + ), + ], + ), + ), + body: Column( + children: [ + Expanded( + child: messagesAsync.when( + loading: () => const Center(child: CircularProgressIndicator()), + error: (e, _) => Center( + child: Text('Error: $e', + style: const TextStyle(color: Colors.redAccent)), + ), + data: (messages) { + final hasStreaming = streamingText != null && streamingText!.isNotEmpty; + final itemCount = messages.length + (hasStreaming ? 1 : 0); + + if (itemCount == 0) { + return const Center( + child: Text( + 'Start the conversation', + style: TextStyle(color: Colors.grey), + ), + ); + } + + return ListView.builder( + controller: scrollController, + padding: const EdgeInsets.symmetric( + horizontal: 12, vertical: 8), + itemCount: itemCount, + itemBuilder: (context, i) { + if (i < messages.length) { + return MessageBubble(message: messages[i]); + } + // Streaming placeholder + return MessageBubble.streaming( + sessionId: sessionId, text: streamingText!); + }, + ); + }, + ), + ), + ChatInputBar( + sessionId: sessionId, + onSend: onSend, + onVoice: onVoice, + ), + ], + ), + ); + } +} diff --git a/apps/mobile/lib/features/chat/presentation/screens/session_list_screen.dart b/apps/mobile/lib/features/chat/presentation/screens/session_list_screen.dart new file mode 100644 index 0000000..e57febb --- /dev/null +++ b/apps/mobile/lib/features/chat/presentation/screens/session_list_screen.dart @@ -0,0 +1,193 @@ +import 'package:flutter/material.dart'; +import 'package:flutter_riverpod/flutter_riverpod.dart'; +import 'package:go_router/go_router.dart'; +import 'package:intl/intl.dart'; + +import '../../../../core/models/session_models.dart'; +import '../../domain/providers/session_provider.dart'; + +class SessionListScreen extends ConsumerWidget { + const SessionListScreen({super.key}); + + @override + Widget build(BuildContext context, WidgetRef ref) { + final sessionsAsync = ref.watch(activeSessionsProvider); + + return Scaffold( + backgroundColor: const Color(0xFF1E1E1E), + appBar: AppBar( + backgroundColor: const Color(0xFF252526), + title: const Text('Sessions'), + ), + floatingActionButton: FloatingActionButton.extended( + onPressed: () => _showAgentPicker(context, ref), + backgroundColor: const Color(0xFF569CD6), + icon: const Icon(Icons.add), + label: const Text('New Session'), + ), + body: sessionsAsync.when( + loading: () => + const Center(child: CircularProgressIndicator()), + error: (e, _) => Center( + child: Text( + 'Error: $e', + style: const TextStyle(color: Colors.redAccent), + ), + ), + data: (sessions) { + if (sessions.isEmpty) { + return const Center( + child: Text( + 'No active sessions.\nTap + to start one.', + textAlign: TextAlign.center, + style: TextStyle(color: Colors.grey), + ), + ); + } + return RefreshIndicator( + onRefresh: () => ref.read(activeSessionsProvider.notifier).refresh(), + child: ListView.separated( + padding: const EdgeInsets.all(8), + itemCount: sessions.length, + separatorBuilder: (_, __) => const SizedBox(height: 4), + itemBuilder: (context, i) => + _SessionTile(session: sessions[i]), + ), + ); + }, + ), + ); + } + + void _showAgentPicker(BuildContext context, WidgetRef ref) { + showModalBottomSheet( + context: context, + backgroundColor: const Color(0xFF252526), + shape: const RoundedRectangleBorder( + borderRadius: BorderRadius.vertical(top: Radius.circular(16)), + ), + builder: (_) => const _AgentPickerSheet(), + ); + } +} + +class _SessionTile extends ConsumerWidget { + final ChatSession session; + const _SessionTile({required this.session}); + + @override + Widget build(BuildContext context, WidgetRef ref) { + final timeLabel = session.lastMessageAt != null + ? DateFormat.jm().format(session.lastMessageAt!) + : ''; + final statusColor = switch (session.status) { + SessionStatus.active => const Color(0xFF4EC9B0), + SessionStatus.paused => Colors.orange, + SessionStatus.closed => Colors.grey, + }; + + return GestureDetector( + onLongPress: () => _confirmDelete(context, ref), + child: ListTile( + tileColor: const Color(0xFF252526), + shape: RoundedRectangleBorder(borderRadius: BorderRadius.circular(8)), + leading: CircleAvatar( + backgroundColor: const Color(0xFF3C3C3C), + child: Text( + session.agentType.substring(0, 1).toUpperCase(), + style: const TextStyle(color: Color(0xFF569CD6)), + ), + ), + title: Text( + session.title.isNotEmpty ? session.title : 'Session ${session.id.substring(0, 8)}', + style: const TextStyle(color: Colors.white), + overflow: TextOverflow.ellipsis, + ), + subtitle: Text( + session.workingDirectory, + style: const TextStyle(color: Colors.grey, fontSize: 12), + overflow: TextOverflow.ellipsis, + ), + trailing: Row( + mainAxisSize: MainAxisSize.min, + children: [ + Text(timeLabel, style: const TextStyle(color: Colors.grey, fontSize: 12)), + const SizedBox(width: 8), + Container( + width: 8, + height: 8, + decoration: BoxDecoration( + color: statusColor, + shape: BoxShape.circle, + ), + ), + ], + ), + onTap: () { + ref.read(currentSessionProvider.notifier).state = session.id; + context.go('/home/chat/${session.id}'); + }, + ), + ); + } + + Future _confirmDelete(BuildContext context, WidgetRef ref) async { + final confirmed = await showDialog( + context: context, + builder: (_) => AlertDialog( + backgroundColor: const Color(0xFF252526), + title: const Text('Delete Session', style: TextStyle(color: Colors.white)), + content: const Text('Remove this session and all its messages?', + style: TextStyle(color: Colors.grey)), + actions: [ + TextButton( + onPressed: () => Navigator.pop(context, false), + child: const Text('Cancel'), + ), + TextButton( + onPressed: () => Navigator.pop(context, true), + child: const Text('Delete', style: TextStyle(color: Colors.redAccent)), + ), + ], + ), + ); + if (confirmed == true) { + await ref.read(activeSessionsProvider.notifier).deleteSession(session.id); + } + } +} + +class _AgentPickerSheet extends ConsumerWidget { + const _AgentPickerSheet(); + + @override + Widget build(BuildContext context, WidgetRef ref) { + return Padding( + padding: const EdgeInsets.all(24), + child: Column( + mainAxisSize: MainAxisSize.min, + crossAxisAlignment: CrossAxisAlignment.stretch, + children: [ + const Text( + 'Pick Agent Type', + style: TextStyle(color: Colors.white, fontSize: 18, fontWeight: FontWeight.bold), + ), + const SizedBox(height: 16), + const Text( + 'Connect a bridge agent first from Settings → Agents.', + style: TextStyle(color: Colors.grey), + ), + const SizedBox(height: 24), + TextButton( + onPressed: () { + Navigator.pop(context); + context.go('/settings/agents'); + }, + child: const Text('Go to Agent Settings', + style: TextStyle(color: Color(0xFF569CD6))), + ), + ], + ), + ); + } +} diff --git a/apps/mobile/lib/features/chat/presentation/widgets/chat_input_bar.dart b/apps/mobile/lib/features/chat/presentation/widgets/chat_input_bar.dart new file mode 100644 index 0000000..8515089 --- /dev/null +++ b/apps/mobile/lib/features/chat/presentation/widgets/chat_input_bar.dart @@ -0,0 +1,139 @@ +import 'package:flutter/material.dart'; +import 'package:flutter_riverpod/flutter_riverpod.dart'; + +import '../../../../core/network/bridge_socket.dart'; + +class ChatInputBar extends ConsumerStatefulWidget { + final String sessionId; + final void Function(String) onSend; + final VoidCallback onVoice; + + const ChatInputBar({ + super.key, + required this.sessionId, + required this.onSend, + required this.onVoice, + }); + + @override + ConsumerState createState() => _ChatInputBarState(); +} + +class _ChatInputBarState extends ConsumerState { + final _controller = TextEditingController(); + bool _hasText = false; + + @override + void initState() { + super.initState(); + _controller.addListener(() { + final newHasText = _controller.text.isNotEmpty; + if (newHasText != _hasText) setState(() => _hasText = newHasText); + }); + } + + @override + void dispose() { + _controller.dispose(); + super.dispose(); + } + + void _send() { + final text = _controller.text.trim(); + if (text.isEmpty) return; + _controller.clear(); + widget.onSend(text); + } + + @override + Widget build(BuildContext context) { + final socketState = ref.watch(bridgeSocketStateProvider); + final isConnected = socketState == BridgeSocketState.connected; + + return Container( + color: const Color(0xFF252526), + padding: const EdgeInsets.fromLTRB(8, 6, 8, 12), + child: Column( + mainAxisSize: MainAxisSize.min, + children: [ + if (!isConnected) + Container( + width: double.infinity, + padding: + const EdgeInsets.symmetric(horizontal: 12, vertical: 4), + color: Colors.orange.withOpacity(0.15), + child: const Row( + mainAxisSize: MainAxisSize.min, + children: [ + Icon(Icons.wifi_off, size: 12, color: Colors.orange), + SizedBox(width: 6), + Text( + 'Offline — reconnecting…', + style: TextStyle(color: Colors.orange, fontSize: 12), + ), + ], + ), + ), + Row( + crossAxisAlignment: CrossAxisAlignment.end, + children: [ + Semantics( + label: 'Voice input', + button: true, + child: IconButton( + icon: const Icon(Icons.mic, color: Color(0xFF9CDCFE)), + onPressed: widget.onVoice, + tooltip: 'Voice input', + ), + ), + Expanded( + child: Semantics( + label: 'Message input', + textField: true, + child: TextField( + controller: _controller, + maxLines: 8, + minLines: 1, + style: const TextStyle(color: Colors.white), + decoration: InputDecoration( + hintText: 'Message…', + hintStyle: const TextStyle(color: Colors.grey), + filled: true, + fillColor: const Color(0xFF3C3C3C), + contentPadding: const EdgeInsets.symmetric( + horizontal: 12, vertical: 8), + border: OutlineInputBorder( + borderRadius: BorderRadius.circular(8), + borderSide: BorderSide.none, + ), + counterText: _controller.text.length > 200 + ? '${_controller.text.length} chars' + : null, + counterStyle: const TextStyle( + color: Colors.grey, fontSize: 11), + ), + textInputAction: TextInputAction.newline, + ), + ), + ), + const SizedBox(width: 4), + AnimatedOpacity( + opacity: (_hasText && isConnected) ? 1.0 : 0.4, + duration: const Duration(milliseconds: 150), + child: Semantics( + label: 'Send message', + button: true, + child: IconButton( + icon: const Icon(Icons.send, color: Color(0xFF569CD6)), + onPressed: (_hasText && isConnected) ? _send : null, + tooltip: 'Send', + ), + ), + ), + ], + ), + ], + ), + ); + } +} diff --git a/apps/mobile/lib/features/chat/presentation/widgets/message_bubble.dart b/apps/mobile/lib/features/chat/presentation/widgets/message_bubble.dart new file mode 100644 index 0000000..832d910 --- /dev/null +++ b/apps/mobile/lib/features/chat/presentation/widgets/message_bubble.dart @@ -0,0 +1,112 @@ +import 'package:flutter/material.dart'; +import 'package:intl/intl.dart'; + +import '../../../../core/models/message_models.dart'; +import 'message_part_widget.dart'; +import 'streaming_text.dart'; + +class MessageBubble extends StatelessWidget { + final Message? message; + final bool isStreaming; + final String? streamingSessionId; + final String? streamingText; + + const MessageBubble({ + super.key, + required Message this.message, + }) : isStreaming = false, + streamingSessionId = null, + streamingText = null; + + const MessageBubble.streaming({ + super.key, + required String sessionId, + required String text, + }) : message = null, + isStreaming = true, + streamingSessionId = sessionId, + streamingText = text; + + @override + Widget build(BuildContext context) { + if (isStreaming) { + return _BubbleLayout( + isUser: false, + timestamp: null, + child: StreamingText(text: streamingText ?? '', isStreaming: true), + ); + } + + final msg = message!; + final isUser = msg.role == MessageRole.user; + + return TweenAnimationBuilder( + tween: Tween(begin: 0, end: 1), + duration: const Duration(milliseconds: 250), + builder: (context, value, child) => Opacity(opacity: value, child: child), + child: GestureDetector( + onLongPress: () => _showTimestamp(context, msg.createdAt), + child: _BubbleLayout( + isUser: isUser, + timestamp: null, + child: isUser + ? Text( + msg.content, + style: const TextStyle(color: Colors.white), + ) + : Column( + crossAxisAlignment: CrossAxisAlignment.start, + children: msg.parts + .map((p) => MessagePartWidget(part: p)) + .toList(), + ), + ), + ), + ); + } + + void _showTimestamp(BuildContext context, DateTime ts) { + ScaffoldMessenger.of(context).showSnackBar( + SnackBar( + content: Text(DateFormat('MMM d, y HH:mm:ss').format(ts)), + duration: const Duration(seconds: 2), + backgroundColor: const Color(0xFF3C3C3C), + ), + ); + } +} + +class _BubbleLayout extends StatelessWidget { + final bool isUser; + final DateTime? timestamp; + final Widget child; + + const _BubbleLayout({ + required this.isUser, + required this.timestamp, + required this.child, + }); + + @override + Widget build(BuildContext context) { + return Align( + alignment: isUser ? Alignment.centerRight : Alignment.centerLeft, + child: Container( + margin: const EdgeInsets.symmetric(vertical: 4), + constraints: BoxConstraints( + maxWidth: MediaQuery.of(context).size.width * 0.78), + decoration: BoxDecoration( + color: isUser ? const Color(0xFF569CD6) : const Color(0xFF252526), + borderRadius: BorderRadius.only( + topLeft: const Radius.circular(12), + topRight: const Radius.circular(12), + bottomLeft: Radius.circular(isUser ? 12 : 4), + bottomRight: Radius.circular(isUser ? 4 : 12), + ), + ), + padding: const EdgeInsets.symmetric(horizontal: 12, vertical: 8), + child: child, + ), + ); + } +} diff --git a/apps/mobile/lib/features/chat/presentation/widgets/message_part_widget.dart b/apps/mobile/lib/features/chat/presentation/widgets/message_part_widget.dart new file mode 100644 index 0000000..c594921 --- /dev/null +++ b/apps/mobile/lib/features/chat/presentation/widgets/message_part_widget.dart @@ -0,0 +1,114 @@ +import 'package:flutter/material.dart'; +import 'package:flutter_markdown/flutter_markdown.dart'; + +import '../../../../core/models/message_models.dart'; +import 'tool_card.dart'; + +class MessagePartWidget extends StatelessWidget { + final MessagePart part; + const MessagePartWidget({super.key, required this.part}); + + @override + Widget build(BuildContext context) { + return part.when( + text: (content) => MarkdownBody( + data: content, + styleSheet: MarkdownStyleSheet( + p: const TextStyle(color: Colors.white, height: 1.4), + code: const TextStyle( + fontFamily: 'JetBrainsMono', + color: Color(0xFF9CDCFE), + backgroundColor: Color(0xFF1E1E1E), + ), + codeblockDecoration: BoxDecoration( + color: const Color(0xFF1E1E1E), + borderRadius: BorderRadius.circular(6), + ), + h1: const TextStyle(color: Color(0xFF569CD6), fontWeight: FontWeight.bold), + h2: const TextStyle(color: Color(0xFF569CD6), fontWeight: FontWeight.bold), + h3: const TextStyle(color: Color(0xFF569CD6)), + blockquote: const TextStyle(color: Color(0xFF9CDCFE)), + listBullet: const TextStyle(color: Colors.grey), + ), + ), + toolUse: (tool, params, id) => ToolCard( + toolName: tool, + params: params, + id: id, + isCompleted: false, + ), + toolResult: (toolCallId, result) => ToolCard( + toolName: toolCallId, + params: const {}, + id: toolCallId, + isCompleted: true, + result: result, + ), + thinking: (content) => _ThinkingBlock(content: content), + ); + } +} + +class _ThinkingBlock extends StatefulWidget { + final String content; + const _ThinkingBlock({required this.content}); + + @override + State<_ThinkingBlock> createState() => _ThinkingBlockState(); +} + +class _ThinkingBlockState extends State<_ThinkingBlock> { + bool _expanded = false; + + @override + Widget build(BuildContext context) { + return GestureDetector( + onTap: () => setState(() => _expanded = !_expanded), + child: Container( + margin: const EdgeInsets.symmetric(vertical: 4), + padding: const EdgeInsets.all(8), + decoration: BoxDecoration( + color: const Color(0xFF1E1E1E), + border: Border.all(color: const Color(0xFF3C3C3C)), + borderRadius: BorderRadius.circular(6), + ), + child: Column( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + Row( + children: [ + const Icon(Icons.psychology, size: 14, color: Colors.grey), + const SizedBox(width: 4), + const Text( + 'Thinking...', + style: TextStyle( + color: Colors.grey, + fontStyle: FontStyle.italic, + fontSize: 12, + ), + ), + const Spacer(), + Icon( + _expanded ? Icons.expand_less : Icons.expand_more, + size: 14, + color: Colors.grey, + ), + ], + ), + if (_expanded) ...[ + const SizedBox(height: 8), + Text( + widget.content, + style: const TextStyle( + color: Colors.grey, + fontStyle: FontStyle.italic, + fontSize: 12, + ), + ), + ], + ], + ), + ), + ); + } +} diff --git a/apps/mobile/lib/features/chat/presentation/widgets/streaming_text.dart b/apps/mobile/lib/features/chat/presentation/widgets/streaming_text.dart new file mode 100644 index 0000000..073fc63 --- /dev/null +++ b/apps/mobile/lib/features/chat/presentation/widgets/streaming_text.dart @@ -0,0 +1,82 @@ +import 'dart:async'; +import 'package:flutter/material.dart'; + +class StreamingText extends StatefulWidget { + final String text; + final bool isStreaming; + + const StreamingText({ + super.key, + required this.text, + this.isStreaming = true, + }); + + @override + State createState() => _StreamingTextState(); +} + +class _StreamingTextState extends State + with SingleTickerProviderStateMixin { + late AnimationController _cursorController; + late Animation _cursorOpacity; + Timer? _cursorTimer; + + @override + void initState() { + super.initState(); + _cursorController = AnimationController( + vsync: this, + duration: const Duration(milliseconds: 530), + ); + _cursorOpacity = + Tween(begin: 0, end: 1).animate(_cursorController); + if (widget.isStreaming) { + _cursorController.repeat(reverse: true); + } + } + + @override + void didUpdateWidget(StreamingText old) { + super.didUpdateWidget(old); + if (!old.isStreaming && widget.isStreaming) { + _cursorController.repeat(reverse: true); + } else if (old.isStreaming && !widget.isStreaming) { + _cursorController.stop(); + _cursorController.value = 0; + } + } + + @override + void dispose() { + _cursorTimer?.cancel(); + _cursorController.dispose(); + super.dispose(); + } + + @override + Widget build(BuildContext context) { + return RichText( + text: TextSpan( + children: [ + TextSpan( + text: widget.text, + style: const TextStyle(color: Colors.white, height: 1.4), + ), + if (widget.isStreaming) + WidgetSpan( + child: FadeTransition( + opacity: _cursorOpacity, + child: const Text( + '|', + style: TextStyle( + color: Color(0xFF569CD6), + fontWeight: FontWeight.w100, + fontSize: 16), + ), + ), + ), + ], + ), + ); + } +} diff --git a/apps/mobile/lib/features/chat/presentation/widgets/tool_card.dart b/apps/mobile/lib/features/chat/presentation/widgets/tool_card.dart new file mode 100644 index 0000000..f28c78b --- /dev/null +++ b/apps/mobile/lib/features/chat/presentation/widgets/tool_card.dart @@ -0,0 +1,299 @@ +import 'package:flutter/material.dart'; + +import '../../../../core/models/message_models.dart'; + +class ToolCard extends StatefulWidget { + final String toolName; + final Map params; + final String? id; + final bool isCompleted; + final ToolResult? result; + + const ToolCard({ + super.key, + required this.toolName, + required this.params, + this.id, + required this.isCompleted, + this.result, + }); + + @override + State createState() => _ToolCardState(); +} + +class _ToolCardState extends State + with SingleTickerProviderStateMixin { + bool _paramsExpanded = false; + bool _resultExpanded = false; + late AnimationController _expandController; + late Animation _expandAnimation; + + @override + void initState() { + super.initState(); + _expandController = AnimationController( + vsync: this, + duration: const Duration(milliseconds: 300), + ); + _expandAnimation = CurvedAnimation( + parent: _expandController, + curve: Curves.easeInOut, + ); + if (widget.isCompleted) _expandController.forward(); + } + + @override + void didUpdateWidget(ToolCard old) { + super.didUpdateWidget(old); + if (!old.isCompleted && widget.isCompleted) { + _expandController.forward(); + setState(() => _resultExpanded = true); + } + } + + @override + void dispose() { + _expandController.dispose(); + super.dispose(); + } + + Color get _statusColor { + if (!widget.isCompleted) return const Color(0xFF569CD6); + return (widget.result?.success ?? false) + ? const Color(0xFF4EC9B0) + : Colors.redAccent; + } + + IconData get _statusIcon { + if (!widget.isCompleted) return Icons.hourglass_empty; + return (widget.result?.success ?? false) ? Icons.check_circle : Icons.error; + } + + String get _statusLabel { + if (!widget.isCompleted) return 'running'; + return (widget.result?.success ?? false) ? 'succeeded' : 'failed'; + } + + @override + Widget build(BuildContext context) { + return Semantics( + label: 'Tool: ${widget.toolName}, status: $_statusLabel', + child: Card( + color: const Color(0xFF2D2D2D), + elevation: 2, + shape: RoundedRectangleBorder(borderRadius: BorderRadius.circular(8)), + margin: const EdgeInsets.symmetric(vertical: 4), + child: Column( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + // Header + Padding( + padding: const EdgeInsets.all(10), + child: Row( + children: [ + _ToolIcon(toolName: widget.toolName), + const SizedBox(width: 8), + Expanded( + child: Text( + widget.toolName, + style: const TextStyle( + color: Colors.white, + fontWeight: FontWeight.w600, + fontFamily: 'JetBrainsMono', + fontSize: 13), + overflow: TextOverflow.ellipsis, + ), + ), + Icon(_statusIcon, color: _statusColor, size: 18), + ], + ), + ), + // Params expandable + if (widget.params.isNotEmpty) + _ExpandableSection( + label: 'Parameters', + expanded: _paramsExpanded, + onTap: () => + setState(() => _paramsExpanded = !_paramsExpanded), + child: _KeyValueList(map: widget.params), + ), + // Result expandable + if (widget.isCompleted && widget.result != null) + SizeTransition( + sizeFactor: _expandAnimation, + child: _ExpandableSection( + label: 'Result', + expanded: _resultExpanded, + onTap: () => + setState(() => _resultExpanded = !_resultExpanded), + child: _ResultContent(result: widget.result!), + ), + ), + ], + ), + ), + ); + } +} + +class _ToolIcon extends StatelessWidget { + final String toolName; + const _ToolIcon({required this.toolName}); + + IconData get _icon { + final name = toolName.toLowerCase(); + if (name.contains('file') || name.contains('read') || name.contains('write')) { + return Icons.description; + } + if (name.contains('bash') || name.contains('shell') || name.contains('exec')) { + return Icons.terminal; + } + if (name.contains('search') || name.contains('grep')) { + return Icons.search; + } + if (name.contains('git')) return Icons.call_split; + if (name.contains('web') || name.contains('http')) return Icons.language; + return Icons.build; + } + + @override + Widget build(BuildContext context) { + return Container( + padding: const EdgeInsets.all(4), + decoration: BoxDecoration( + color: const Color(0xFF3C3C3C), + borderRadius: BorderRadius.circular(4), + ), + child: Icon(_icon, size: 14, color: const Color(0xFF569CD6)), + ); + } +} + +class _ExpandableSection extends StatelessWidget { + final String label; + final bool expanded; + final VoidCallback onTap; + final Widget child; + + const _ExpandableSection({ + required this.label, + required this.expanded, + required this.onTap, + required this.child, + }); + + @override + Widget build(BuildContext context) { + return Column( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + const Divider(color: Color(0xFF3C3C3C), height: 1), + Semantics( + label: 'Expand tool parameters', + button: true, + child: InkWell( + onTap: onTap, + child: Padding( + padding: const EdgeInsets.symmetric(horizontal: 10, vertical: 6), + child: Row( + children: [ + Text(label, + style: const TextStyle( + color: Colors.grey, + fontSize: 11, + fontFamily: 'JetBrainsMono')), + const Spacer(), + Icon( + expanded ? Icons.expand_less : Icons.expand_more, + size: 14, + color: Colors.grey, + ), + ], + ), + ), + ), + ), + if (expanded) + Padding( + padding: const EdgeInsets.fromLTRB(10, 0, 10, 10), + child: child, + ), + ], + ); + } +} + +class _KeyValueList extends StatelessWidget { + final Map map; + const _KeyValueList({required this.map}); + + @override + Widget build(BuildContext context) { + return Column( + crossAxisAlignment: CrossAxisAlignment.start, + children: map.entries.map((e) { + return Padding( + padding: const EdgeInsets.only(bottom: 4), + child: RichText( + text: TextSpan( + children: [ + TextSpan( + text: '${e.key}: ', + style: const TextStyle( + color: Color(0xFF9CDCFE), + fontFamily: 'JetBrainsMono', + fontSize: 12)), + TextSpan( + text: e.value.toString(), + style: const TextStyle( + color: Color(0xFFCE9178), + fontFamily: 'JetBrainsMono', + fontSize: 12)), + ], + ), + ), + ); + }).toList(), + ); + } +} + +class _ResultContent extends StatelessWidget { + final ToolResult result; + const _ResultContent({required this.result}); + + @override + Widget build(BuildContext context) { + return Column( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + if (result.error != null) + Text( + result.error!, + style: const TextStyle( + color: Colors.redAccent, + fontFamily: 'JetBrainsMono', + fontSize: 12), + ) + else + Text( + result.content, + style: const TextStyle( + color: Color(0xFF4EC9B0), + fontFamily: 'JetBrainsMono', + fontSize: 12), + maxLines: 10, + overflow: TextOverflow.ellipsis, + ), + if (result.durationMs != null) ...[ + const SizedBox(height: 4), + Text( + '${result.durationMs}ms', + style: const TextStyle(color: Colors.grey, fontSize: 11), + ), + ], + ], + ); + } +} diff --git a/apps/mobile/lib/features/chat/presentation/widgets/voice_input_sheet.dart b/apps/mobile/lib/features/chat/presentation/widgets/voice_input_sheet.dart new file mode 100644 index 0000000..5f21dc0 --- /dev/null +++ b/apps/mobile/lib/features/chat/presentation/widgets/voice_input_sheet.dart @@ -0,0 +1,195 @@ +import 'dart:math'; +import 'package:flutter/material.dart'; +import 'package:speech_to_text/speech_to_text.dart' as stt; + +class VoiceInputSheet extends StatefulWidget { + final void Function(String text) onSend; + + const VoiceInputSheet({super.key, required this.onSend}); + + @override + State createState() => _VoiceInputSheetState(); +} + +class _VoiceInputSheetState extends State + with SingleTickerProviderStateMixin { + final _speech = stt.SpeechToText(); + bool _listening = false; + String _transcript = ''; + late AnimationController _pulseController; + late Animation _pulseAnimation; + + @override + void initState() { + super.initState(); + _pulseController = AnimationController( + vsync: this, + duration: const Duration(milliseconds: 800), + ); + _pulseAnimation = Tween(begin: 0.9, end: 1.1).animate( + CurvedAnimation(parent: _pulseController, curve: Curves.easeInOut), + ); + _startListening(); + } + + Future _startListening() async { + final available = await _speech.initialize( + onStatus: (status) { + if (status == 'done' || status == 'notListening') { + if (mounted) setState(() => _listening = false); + _pulseController.stop(); + } + }, + onError: (_) { + if (mounted) setState(() => _listening = false); + _pulseController.stop(); + }, + ); + if (!available) return; + + await _speech.listen( + onResult: (result) { + if (mounted) { + setState(() => _transcript = result.recognizedWords); + } + }, + listenFor: const Duration(seconds: 30), + pauseFor: const Duration(seconds: 3), + ); + if (mounted) setState(() => _listening = true); + _pulseController.repeat(reverse: true); + } + + Future _stopListening() async { + await _speech.stop(); + _pulseController.stop(); + if (mounted) setState(() => _listening = false); + } + + @override + void dispose() { + _speech.stop(); + _pulseController.dispose(); + super.dispose(); + } + + @override + Widget build(BuildContext context) { + return Container( + decoration: const BoxDecoration( + color: Color(0xFF252526), + borderRadius: BorderRadius.vertical(top: Radius.circular(20)), + ), + padding: const EdgeInsets.fromLTRB(24, 16, 24, 32), + child: Column( + mainAxisSize: MainAxisSize.min, + children: [ + Container( + width: 40, + height: 4, + decoration: BoxDecoration( + color: Colors.grey, + borderRadius: BorderRadius.circular(2), + ), + ), + const SizedBox(height: 24), + AnimatedBuilder( + animation: _pulseAnimation, + builder: (context, child) => Transform.scale( + scale: _listening ? _pulseAnimation.value : 1.0, + child: child, + ), + child: Container( + width: 80, + height: 80, + decoration: BoxDecoration( + shape: BoxShape.circle, + color: _listening + ? const Color(0xFF569CD6).withOpacity(0.2) + : const Color(0xFF3C3C3C), + border: Border.all( + color: _listening + ? const Color(0xFF569CD6) + : Colors.grey, + width: 2, + ), + ), + child: Icon( + _listening ? Icons.mic : Icons.mic_off, + color: _listening + ? const Color(0xFF569CD6) + : Colors.grey, + size: 36, + ), + ), + ), + const SizedBox(height: 16), + Text( + _listening ? 'Listening…' : 'Tap mic to start', + style: TextStyle( + color: _listening + ? const Color(0xFF569CD6) + : Colors.grey, + fontSize: 14, + ), + ), + const SizedBox(height: 20), + Container( + width: double.infinity, + constraints: const BoxConstraints(minHeight: 60), + padding: const EdgeInsets.all(12), + decoration: BoxDecoration( + color: const Color(0xFF1E1E1E), + borderRadius: BorderRadius.circular(8), + ), + child: Text( + _transcript.isEmpty ? 'Your words will appear here…' : _transcript, + style: TextStyle( + color: _transcript.isEmpty ? Colors.grey : Colors.white, + fontStyle: _transcript.isEmpty + ? FontStyle.italic + : FontStyle.normal, + ), + ), + ), + const SizedBox(height: 20), + Row( + children: [ + Expanded( + child: OutlinedButton( + onPressed: () => Navigator.pop(context), + style: OutlinedButton.styleFrom( + side: const BorderSide(color: Colors.grey), + padding: const EdgeInsets.symmetric(vertical: 14), + shape: RoundedRectangleBorder( + borderRadius: BorderRadius.circular(8)), + ), + child: const Text('Cancel', + style: TextStyle(color: Colors.grey)), + ), + ), + const SizedBox(width: 12), + Expanded( + child: FilledButton( + onPressed: _transcript.isEmpty + ? null + : () { + _stopListening(); + widget.onSend(_transcript); + }, + style: FilledButton.styleFrom( + backgroundColor: const Color(0xFF569CD6), + padding: const EdgeInsets.symmetric(vertical: 14), + shape: RoundedRectangleBorder( + borderRadius: BorderRadius.circular(8)), + ), + child: const Text('Send'), + ), + ), + ], + ), + ], + ), + ); + } +} diff --git a/apps/mobile/lib/features/diff/domain/providers/diff_provider.dart b/apps/mobile/lib/features/diff/domain/providers/diff_provider.dart new file mode 100644 index 0000000..6e1c313 --- /dev/null +++ b/apps/mobile/lib/features/diff/domain/providers/diff_provider.dart @@ -0,0 +1,45 @@ +import 'package:flutter_riverpod/flutter_riverpod.dart'; +import 'package:riverpod_annotation/riverpod_annotation.dart'; + +import '../../../../core/models/git_models.dart'; +import '../../../../core/network/bridge_socket.dart'; + +part 'diff_provider.g.dart'; + +enum DiffViewMode { unified, splitView } + +final currentDiffProvider = StateProvider?>((ref) => null); + +final diffViewModeProvider = + StateProvider((ref) => DiffViewMode.unified); + +@riverpod +class DiffNotifier extends _$DiffNotifier { + @override + Future build() async { + final socket = ref.watch(bridgeSocketProvider); + socket.messageStream.listen((msg) { + if (msg['type'] == 'diff_result') { + final rawFiles = msg['files'] as List? ?? []; + final files = rawFiles + .whereType>() + .map((f) => DiffFile.fromJson(f)) + .toList(); + ref.read(currentDiffProvider.notifier).state = files; + } + }); + } + + Future requestDiff(String sessionId, {List? files}) async { + final socket = ref.read(bridgeSocketProvider); + socket.send({ + 'type': 'request_diff', + 'session_id': sessionId, + if (files != null) 'files': files, + }); + } + + void clearDiff() { + ref.read(currentDiffProvider.notifier).state = null; + } +} diff --git a/apps/mobile/lib/features/diff/domain/providers/diff_provider.g.dart b/apps/mobile/lib/features/diff/domain/providers/diff_provider.g.dart new file mode 100644 index 0000000..c43533f --- /dev/null +++ b/apps/mobile/lib/features/diff/domain/providers/diff_provider.g.dart @@ -0,0 +1,25 @@ +// GENERATED CODE - DO NOT MODIFY BY HAND + +part of 'diff_provider.dart'; + +// ************************************************************************** +// RiverpodGenerator +// ************************************************************************** + +String _$diffNotifierHash() => r'89a62a84c8ba9e5bd406efb244969816bd3f4ebf'; + +/// See also [DiffNotifier]. +@ProviderFor(DiffNotifier) +final diffNotifierProvider = + AutoDisposeAsyncNotifierProvider.internal( + DiffNotifier.new, + name: r'diffNotifierProvider', + debugGetCreateSourceHash: + const bool.fromEnvironment('dart.vm.product') ? null : _$diffNotifierHash, + dependencies: null, + allTransitiveDependencies: null, +); + +typedef _$DiffNotifier = AutoDisposeAsyncNotifier; +// ignore_for_file: type=lint +// ignore_for_file: subtype_of_sealed_class, invalid_use_of_internal_member, invalid_use_of_visible_for_testing_member, deprecated_member_use_from_same_package diff --git a/apps/mobile/lib/features/diff/presentation/screens/diff_viewer_screen.dart b/apps/mobile/lib/features/diff/presentation/screens/diff_viewer_screen.dart new file mode 100644 index 0000000..2b844a4 --- /dev/null +++ b/apps/mobile/lib/features/diff/presentation/screens/diff_viewer_screen.dart @@ -0,0 +1,239 @@ +import 'package:flutter/material.dart'; +import 'package:flutter_riverpod/flutter_riverpod.dart'; + +import '../../../../core/models/git_models.dart'; +import '../../domain/providers/diff_provider.dart'; +import '../widgets/diff_viewer.dart'; +import '../widgets/diff_hunk_view.dart'; + +class DiffViewerScreen extends ConsumerStatefulWidget { + const DiffViewerScreen({super.key}); + + @override + ConsumerState createState() => _DiffViewerScreenState(); +} + +class _DiffViewerScreenState extends ConsumerState { + int _selectedFileIndex = 0; + + String _statusLabel(FileChangeStatus status) { + return switch (status) { + FileChangeStatus.modified => 'M', + FileChangeStatus.added => 'A', + FileChangeStatus.deleted => 'D', + FileChangeStatus.renamed => 'R', + FileChangeStatus.untracked => '?', + }; + } + + Color _statusColor(FileChangeStatus status) { + return switch (status) { + FileChangeStatus.modified => Colors.orange, + FileChangeStatus.added => const Color(0xFF4EC9B0), + FileChangeStatus.deleted => Colors.redAccent, + FileChangeStatus.renamed => const Color(0xFF569CD6), + FileChangeStatus.untracked => Colors.grey, + }; + } + + Widget _buildFileSidebar(List files, DiffViewMode viewMode) { + return ListView.builder( + itemCount: files.length, + itemBuilder: (context, index) { + final file = files[index]; + final isSelected = index == _selectedFileIndex; + final color = _statusColor(file.status); + return InkWell( + onTap: () => setState(() => _selectedFileIndex = index), + child: Container( + color: isSelected + ? const Color(0xFF2A2D2E) + : Colors.transparent, + padding: const EdgeInsets.symmetric(horizontal: 10, vertical: 8), + child: Row( + children: [ + Container( + width: 18, + height: 18, + decoration: BoxDecoration( + color: color.withOpacity(0.2), + borderRadius: BorderRadius.circular(3), + ), + alignment: Alignment.center, + child: Text( + _statusLabel(file.status), + style: TextStyle( + color: color, + fontSize: 10, + fontWeight: FontWeight.bold, + fontFamily: 'JetBrainsMono', + ), + ), + ), + const SizedBox(width: 8), + Expanded( + child: Column( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + Text( + file.path.split('/').last, + style: const TextStyle( + color: Colors.white, + fontSize: 12, + fontFamily: 'JetBrainsMono', + ), + overflow: TextOverflow.ellipsis, + ), + Row( + children: [ + Text( + '+${file.additions}', + style: const TextStyle( + color: Color(0xFF4EC9B0), + fontSize: 10, + fontFamily: 'JetBrainsMono', + ), + ), + const SizedBox(width: 4), + Text( + '-${file.deletions}', + style: const TextStyle( + color: Colors.redAccent, + fontSize: 10, + fontFamily: 'JetBrainsMono', + ), + ), + ], + ), + ], + ), + ), + ], + ), + ), + ); + }, + ); + } + + Widget _buildDiffDetail(DiffFile file, DiffViewMode viewMode) { + if (file.hunks.isEmpty) { + return const Center( + child: Text( + 'No hunks to display', + style: TextStyle(color: Colors.grey), + ), + ); + } + return ListView.builder( + padding: const EdgeInsets.all(8), + itemCount: file.hunks.length, + itemBuilder: (context, i) => + DiffHunkView(hunk: file.hunks[i], viewMode: viewMode), + ); + } + + @override + Widget build(BuildContext context) { + final diff = ref.watch(currentDiffProvider); + final viewMode = ref.watch(diffViewModeProvider); + + final fileCount = diff?.length ?? 0; + final additions = diff?.fold(0, (sum, f) => sum + f.additions) ?? 0; + final deletions = diff?.fold(0, (sum, f) => sum + f.deletions) ?? 0; + + return Scaffold( + backgroundColor: const Color(0xFF1E1E1E), + appBar: AppBar( + backgroundColor: const Color(0xFF252526), + title: Row( + children: [ + Text( + '$fileCount ${fileCount == 1 ? 'file' : 'files'}', + style: const TextStyle(color: Colors.white), + ), + const SizedBox(width: 12), + Text( + '+$additions', + style: const TextStyle(color: Color(0xFF4EC9B0), fontSize: 13), + ), + const SizedBox(width: 6), + Text( + '-$deletions', + style: const TextStyle(color: Colors.redAccent, fontSize: 13), + ), + ], + ), + actions: [ + IconButton( + tooltip: viewMode == DiffViewMode.unified + ? 'Switch to split view' + : 'Switch to unified view', + icon: Icon( + viewMode == DiffViewMode.unified + ? Icons.vertical_split + : Icons.view_stream, + color: const Color(0xFF9CDCFE), + ), + onPressed: () { + ref.read(diffViewModeProvider.notifier).state = + viewMode == DiffViewMode.unified + ? DiffViewMode.splitView + : DiffViewMode.unified; + }, + ), + ], + ), + body: diff == null || diff.isEmpty + ? const Center( + child: Column( + mainAxisSize: MainAxisSize.min, + children: [ + Icon(Icons.difference_outlined, size: 48, color: Colors.grey), + SizedBox(height: 12), + Text( + 'No diff to display', + style: TextStyle(color: Colors.grey), + ), + ], + ), + ) + : LayoutBuilder( + builder: (context, constraints) { + final isTabletLandscape = constraints.maxWidth >= 600; + + if (isTabletLandscape) { + // Clamp selected index in case diff changed + final safeIndex = + _selectedFileIndex.clamp(0, diff.length - 1); + + return Row( + children: [ + // Left 35%: file list sidebar + SizedBox( + width: constraints.maxWidth * 0.35, + child: Container( + decoration: const BoxDecoration( + color: Color(0xFF252526), + border: Border( + right: BorderSide(color: Color(0xFF3C3C3C)), + ), + ), + child: _buildFileSidebar(diff, viewMode), + ), + ), + // Right 65%: selected file diff hunks + Expanded( + child: _buildDiffDetail(diff[safeIndex], viewMode), + ), + ], + ); + } + + // Portrait: original single-panel ListView + return DiffViewer(files: diff, viewMode: viewMode); + }, + ), + ); + } +} diff --git a/apps/mobile/lib/features/diff/presentation/widgets/diff_file_card.dart b/apps/mobile/lib/features/diff/presentation/widgets/diff_file_card.dart new file mode 100644 index 0000000..ca44eed --- /dev/null +++ b/apps/mobile/lib/features/diff/presentation/widgets/diff_file_card.dart @@ -0,0 +1,105 @@ +import 'package:flutter/material.dart'; + +import '../../../../core/models/git_models.dart'; +import '../../domain/providers/diff_provider.dart'; +import 'diff_hunk_view.dart'; + +class DiffFileCard extends StatelessWidget { + final DiffFile file; + final DiffViewMode viewMode; + + const DiffFileCard({ + super.key, + required this.file, + required this.viewMode, + }); + + String get _statusLabel { + return switch (file.status) { + FileChangeStatus.modified => 'M', + FileChangeStatus.added => 'A', + FileChangeStatus.deleted => 'D', + FileChangeStatus.renamed => 'R', + FileChangeStatus.untracked => '?', + }; + } + + Color get _statusColor { + return switch (file.status) { + FileChangeStatus.modified => Colors.orange, + FileChangeStatus.added => const Color(0xFF4EC9B0), + FileChangeStatus.deleted => Colors.redAccent, + FileChangeStatus.renamed => const Color(0xFF569CD6), + FileChangeStatus.untracked => Colors.grey, + }; + } + + @override + Widget build(BuildContext context) { + return Card( + color: const Color(0xFF252526), + margin: const EdgeInsets.only(bottom: 8), + shape: RoundedRectangleBorder(borderRadius: BorderRadius.circular(8)), + child: ExpansionTile( + tilePadding: const EdgeInsets.symmetric(horizontal: 12, vertical: 4), + childrenPadding: EdgeInsets.zero, + collapsedBackgroundColor: Colors.transparent, + backgroundColor: Colors.transparent, + shape: const Border(), + collapsedShape: const Border(), + leading: Container( + width: 20, + height: 20, + decoration: BoxDecoration( + color: _statusColor.withOpacity(0.2), + borderRadius: BorderRadius.circular(4), + ), + alignment: Alignment.center, + child: Text( + _statusLabel, + style: TextStyle( + color: _statusColor, + fontSize: 11, + fontWeight: FontWeight.bold, + fontFamily: 'JetBrainsMono', + ), + ), + ), + title: Text( + file.path, + style: const TextStyle( + color: Colors.white, + fontSize: 13, + fontFamily: 'JetBrainsMono', + ), + overflow: TextOverflow.ellipsis, + ), + trailing: Row( + mainAxisSize: MainAxisSize.min, + children: [ + Text( + '+${file.additions}', + style: const TextStyle( + color: Color(0xFF4EC9B0), + fontSize: 12, + fontFamily: 'JetBrainsMono'), + ), + const SizedBox(width: 6), + Text( + '-${file.deletions}', + style: const TextStyle( + color: Colors.redAccent, + fontSize: 12, + fontFamily: 'JetBrainsMono'), + ), + const SizedBox(width: 4), + const Icon(Icons.expand_more, color: Colors.grey, size: 16), + ], + ), + children: file.hunks + .map((h) => DiffHunkView(hunk: h, viewMode: viewMode)) + .toList(), + ), + ); + } +} diff --git a/apps/mobile/lib/features/diff/presentation/widgets/diff_hunk_view.dart b/apps/mobile/lib/features/diff/presentation/widgets/diff_hunk_view.dart new file mode 100644 index 0000000..a10deee --- /dev/null +++ b/apps/mobile/lib/features/diff/presentation/widgets/diff_hunk_view.dart @@ -0,0 +1,41 @@ +import 'package:flutter/material.dart'; + +import '../../../../core/models/git_models.dart'; +import '../../domain/providers/diff_provider.dart'; +import 'diff_line_widget.dart'; + +class DiffHunkView extends StatelessWidget { + final DiffHunk hunk; + final DiffViewMode viewMode; + + const DiffHunkView({ + super.key, + required this.hunk, + required this.viewMode, + }); + + @override + Widget build(BuildContext context) { + return Column( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + // Hunk header + Container( + width: double.infinity, + color: const Color(0xFF1E1E1E), + padding: const EdgeInsets.symmetric(horizontal: 8, vertical: 4), + child: Text( + hunk.header, + style: const TextStyle( + color: Colors.grey, + fontFamily: 'JetBrainsMono', + fontSize: 12, + ), + ), + ), + // Lines + ...hunk.lines.map((line) => DiffLineWidget(line: line)), + ], + ); + } +} diff --git a/apps/mobile/lib/features/diff/presentation/widgets/diff_line_widget.dart b/apps/mobile/lib/features/diff/presentation/widgets/diff_line_widget.dart new file mode 100644 index 0000000..8c26f73 --- /dev/null +++ b/apps/mobile/lib/features/diff/presentation/widgets/diff_line_widget.dart @@ -0,0 +1,97 @@ +import 'package:flutter/material.dart'; + +import '../../../../core/models/git_models.dart'; + +class DiffLineWidget extends StatelessWidget { + final DiffLine line; + const DiffLineWidget({super.key, required this.line}); + + Color get _backgroundColor { + return switch (line.type) { + DiffLineType.added => const Color(0xFF1A3A1A), + DiffLineType.removed => const Color(0xFF3A1A1A), + DiffLineType.context => Colors.transparent, + }; + } + + String get _prefix { + return switch (line.type) { + DiffLineType.added => '+', + DiffLineType.removed => '-', + DiffLineType.context => ' ', + }; + } + + Color get _prefixColor { + return switch (line.type) { + DiffLineType.added => const Color(0xFF4EC9B0), + DiffLineType.removed => Colors.redAccent, + DiffLineType.context => Colors.grey, + }; + } + + @override + Widget build(BuildContext context) { + return Container( + color: _backgroundColor, + child: Row( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + // Old line number gutter + SizedBox( + width: 36, + child: Text( + line.oldLineNumber?.toString() ?? '', + textAlign: TextAlign.right, + style: const TextStyle( + color: Colors.grey, + fontFamily: 'JetBrainsMono', + fontSize: 11, + ), + ), + ), + // New line number gutter + SizedBox( + width: 36, + child: Text( + line.newLineNumber?.toString() ?? '', + textAlign: TextAlign.right, + style: const TextStyle( + color: Colors.grey, + fontFamily: 'JetBrainsMono', + fontSize: 11, + ), + ), + ), + // Prefix (+/-/space) + Padding( + padding: const EdgeInsets.symmetric(horizontal: 6), + child: Text( + _prefix, + style: TextStyle( + color: _prefixColor, + fontFamily: 'JetBrainsMono', + fontSize: 12, + fontWeight: FontWeight.bold, + ), + ), + ), + // Content + Expanded( + child: Text( + line.content, + style: TextStyle( + color: line.type == DiffLineType.context + ? const Color(0xFFD4D4D4) + : Colors.white, + fontFamily: 'JetBrainsMono', + fontSize: 12, + ), + softWrap: true, + ), + ), + ], + ), + ); + } +} diff --git a/apps/mobile/lib/features/diff/presentation/widgets/diff_viewer.dart b/apps/mobile/lib/features/diff/presentation/widgets/diff_viewer.dart new file mode 100644 index 0000000..24b1dc6 --- /dev/null +++ b/apps/mobile/lib/features/diff/presentation/widgets/diff_viewer.dart @@ -0,0 +1,28 @@ +import 'package:flutter/material.dart'; + +import '../../../../core/models/git_models.dart'; +import '../../domain/providers/diff_provider.dart'; +import 'diff_file_card.dart'; + +class DiffViewer extends StatelessWidget { + final List files; + final DiffViewMode viewMode; + + const DiffViewer({ + super.key, + required this.files, + required this.viewMode, + }); + + @override + Widget build(BuildContext context) { + return ListView.builder( + padding: const EdgeInsets.all(8), + itemCount: files.length, + itemBuilder: (context, i) => DiffFileCard( + file: files[i], + viewMode: viewMode, + ), + ); + } +} diff --git a/apps/mobile/lib/features/git/domain/providers/git_provider.dart b/apps/mobile/lib/features/git/domain/providers/git_provider.dart new file mode 100644 index 0000000..bba04d0 --- /dev/null +++ b/apps/mobile/lib/features/git/domain/providers/git_provider.dart @@ -0,0 +1,101 @@ +import 'dart:async'; + +import 'package:flutter_riverpod/flutter_riverpod.dart'; + +import '../../../../core/models/git_models.dart'; +import '../../../../core/network/websocket_messages.dart'; +import '../../../../core/providers/websocket_provider.dart'; +import '../../../diff/domain/providers/diff_provider.dart'; + +// --------------------------------------------------------------------------- +// GitStatus provider (AsyncNotifierProvider.family) +// --------------------------------------------------------------------------- + +final gitStatusProvider = AsyncNotifierProvider.family( + GitNotifier.new, +); + +class GitNotifier extends FamilyAsyncNotifier { + StreamSubscription? _sub; + + @override + Future build(String arg) async { + final service = ref.watch(webSocketServiceProvider); + + _sub?.cancel(); + _sub = service.messages.listen(_handleMessage); + ref.onDispose(() => _sub?.cancel()); + + return null; + } + + void _handleMessage(BridgeMessage msg) { + if (msg.type == BridgeMessageType.gitStatusResponse) { + final payload = msg.payload; + try { + final status = GitStatus.fromJson(payload); + state = AsyncValue.data(status); + } catch (_) { + // Malformed payload — ignore. + } + } + + if (msg.type == BridgeMessageType.gitDiffResponse) { + final rawFiles = msg.payload['files'] as List? ?? []; + final files = rawFiles + .whereType>() + .map(DiffFile.fromJson) + .toList(); + ref.read(currentDiffProvider.notifier).state = files; + } + } + + /// Sends a `git_status_request` and awaits a `git_status_response`. + Future fetchStatus(String sessionId) async { + state = const AsyncValue.loading(); + final service = ref.read(webSocketServiceProvider); + service.send(BridgeMessage.gitStatusRequest(sessionId: sessionId)); + // State will be updated by _handleMessage on response. + } + + /// Sends a `git_commit` message. + Future commit( + String sessionId, + String message, [ + List? files, + ]) async { + final service = ref.read(webSocketServiceProvider); + service.send(BridgeMessage.gitCommit( + sessionId: sessionId, + commitMessage: message, + files: files, + )); + } + + /// Sends a `git_diff` request; response populates [currentDiffProvider]. + Future fetchDiff(String sessionId) async { + final service = ref.read(webSocketServiceProvider); + service.send(BridgeMessage.gitDiff(sessionId: sessionId)); + } + + /// Sends a `git_pull` message. + Future pull(String sessionId) async { + final service = ref.read(webSocketServiceProvider); + // git_pull is not a first-class BridgeMessageType; tunnel via claudeEvent. + service.send(BridgeMessage( + type: BridgeMessageType.claudeEvent, + timestamp: DateTime.now().toUtc(), + payload: {'type': 'git_pull', 'session_id': sessionId}, + )); + } + + /// Sends a `git_push` message. + Future push(String sessionId) async { + final service = ref.read(webSocketServiceProvider); + service.send(BridgeMessage( + type: BridgeMessageType.claudeEvent, + timestamp: DateTime.now().toUtc(), + payload: {'type': 'git_push', 'session_id': sessionId}, + )); + } +} diff --git a/apps/mobile/lib/features/git/presentation/screens/commit_screen.dart b/apps/mobile/lib/features/git/presentation/screens/commit_screen.dart new file mode 100644 index 0000000..09c87fe --- /dev/null +++ b/apps/mobile/lib/features/git/presentation/screens/commit_screen.dart @@ -0,0 +1,131 @@ +import 'package:flutter/material.dart'; +import 'package:flutter_riverpod/flutter_riverpod.dart'; + +import '../../../../core/models/git_models.dart'; +import '../../domain/providers/git_provider.dart'; + +/// Commit screen: compose a commit message and select which changed files +/// to include in the commit. +class CommitScreen extends ConsumerStatefulWidget { + final String sessionId; + final List changes; + + const CommitScreen({ + super.key, + required this.sessionId, + required this.changes, + }); + + @override + ConsumerState createState() => _CommitScreenState(); +} + +class _CommitScreenState extends ConsumerState { + final _messageController = TextEditingController(); + late final List _checked; + bool _isCommitting = false; + + @override + void initState() { + super.initState(); + _checked = List.filled(widget.changes.length, true); + _messageController.addListener(() => setState(() {})); + } + + @override + void dispose() { + _messageController.dispose(); + super.dispose(); + } + + bool get _canCommit => + _messageController.text.trim().isNotEmpty && !_isCommitting; + + Future _commit() async { + if (!_canCommit) return; + setState(() => _isCommitting = true); + + final selectedFiles = []; + for (var i = 0; i < widget.changes.length; i++) { + if (_checked[i]) selectedFiles.add(widget.changes[i].path); + } + + await ref + .read(gitStatusProvider(widget.sessionId).notifier) + .commit( + widget.sessionId, + _messageController.text.trim(), + selectedFiles.isEmpty ? null : selectedFiles, + ); + + if (mounted) { + setState(() => _isCommitting = false); + Navigator.of(context).pop(); + ScaffoldMessenger.of(context).showSnackBar( + const SnackBar(content: Text('Commit sent')), + ); + } + } + + @override + Widget build(BuildContext context) { + return Scaffold( + appBar: AppBar( + title: const Text('Commit'), + actions: [ + TextButton( + onPressed: _canCommit ? _commit : null, + child: _isCommitting + ? const SizedBox( + width: 18, + height: 18, + child: CircularProgressIndicator(strokeWidth: 2), + ) + : const Text('Commit'), + ), + ], + ), + body: Column( + children: [ + Padding( + padding: const EdgeInsets.all(16), + child: TextField( + controller: _messageController, + minLines: 3, + maxLines: 6, + autofocus: true, + decoration: const InputDecoration( + hintText: 'Commit message…', + alignLabelWithHint: true, + ), + ), + ), + const Divider(height: 1), + Expanded( + child: ListView.builder( + itemCount: widget.changes.length, + itemBuilder: (context, index) { + final change = widget.changes[index]; + return CheckboxListTile( + dense: true, + value: _checked[index], + onChanged: (v) => + setState(() => _checked[index] = v ?? false), + title: Text( + change.path, + style: const TextStyle( + fontSize: 13, + fontFamily: 'JetBrainsMono', + ), + overflow: TextOverflow.ellipsis, + ), + controlAffinity: ListTileControlAffinity.leading, + ); + }, + ), + ), + ], + ), + ); + } +} diff --git a/apps/mobile/lib/features/git/presentation/screens/git_screen.dart b/apps/mobile/lib/features/git/presentation/screens/git_screen.dart new file mode 100644 index 0000000..7ff4dec --- /dev/null +++ b/apps/mobile/lib/features/git/presentation/screens/git_screen.dart @@ -0,0 +1,185 @@ +import 'package:flutter/material.dart'; +import 'package:flutter_riverpod/flutter_riverpod.dart'; +import 'package:go_router/go_router.dart'; + +import '../../domain/providers/git_provider.dart'; +import '../widgets/file_change_tile.dart'; +import '../widgets/git_status_card.dart'; + +/// Main Git screen showing repository status and a list of changed files. +/// +/// Requires a [sessionId] to scope WS requests. The session ID is taken from +/// the `extra` field of the route or falls back to an empty string for +/// demonstration purposes when navigated from the bottom nav. +class GitScreen extends ConsumerStatefulWidget { + final String sessionId; + + const GitScreen({super.key, this.sessionId = ''}); + + @override + ConsumerState createState() => _GitScreenState(); +} + +class _GitScreenState extends ConsumerState { + @override + void initState() { + super.initState(); + if (widget.sessionId.isNotEmpty) { + WidgetsBinding.instance.addPostFrameCallback((_) { + ref.read(gitStatusProvider(widget.sessionId).notifier) + .fetchStatus(widget.sessionId); + }); + } + } + + Future _refresh() async { + if (widget.sessionId.isNotEmpty) { + await ref + .read(gitStatusProvider(widget.sessionId).notifier) + .fetchStatus(widget.sessionId); + } + } + + void _onPull() { + if (widget.sessionId.isNotEmpty) { + ref + .read(gitStatusProvider(widget.sessionId).notifier) + .pull(widget.sessionId); + } + } + + void _onPush() { + if (widget.sessionId.isNotEmpty) { + ref + .read(gitStatusProvider(widget.sessionId).notifier) + .push(widget.sessionId); + } + } + + void _onCommit(List changes) { + context.push( + '/git/commit', + extra: {'sessionId': widget.sessionId, 'changes': changes}, + ); + } + + @override + Widget build(BuildContext context) { + final statusAsync = widget.sessionId.isNotEmpty + ? ref.watch(gitStatusProvider(widget.sessionId)) + : const AsyncValue.data(null); + + return Scaffold( + appBar: AppBar(title: const Text('Git')), + body: RefreshIndicator( + onRefresh: _refresh, + child: statusAsync.when( + loading: () => const Center(child: CircularProgressIndicator()), + error: (e, _) => Center(child: Text('Error: $e')), + data: (status) { + if (status == null) { + return _emptyState(); + } + + if (status.isClean) { + return Column( + children: [ + GitStatusCard(status: status), + Expanded(child: _emptyState()), + ], + ); + } + + return Column( + children: [ + GitStatusCard(status: status), + const Divider(height: 1), + Expanded( + child: ListView.builder( + itemCount: status.changes.length, + itemBuilder: (context, index) { + final change = status.changes[index]; + return FileChangeTile( + change: change, + onTap: () {}, + ); + }, + ), + ), + _ActionRow( + onPull: _onPull, + onCommit: () => _onCommit(status.changes), + onPush: _onPush, + ), + ], + ); + }, + ), + ), + ); + } + + Widget _emptyState() { + return Center( + child: Column( + mainAxisSize: MainAxisSize.min, + children: const [ + Icon(Icons.check_circle_outline, + size: 48, color: Color(0xFF4CAF50)), + SizedBox(height: 12), + Text( + 'Repository is clean', + style: TextStyle(fontSize: 15, color: Color(0xFF9E9E9E)), + ), + ], + ), + ); + } +} + +class _ActionRow extends StatelessWidget { + final VoidCallback onPull; + final VoidCallback onCommit; + final VoidCallback onPush; + + const _ActionRow({ + required this.onPull, + required this.onCommit, + required this.onPush, + }); + + @override + Widget build(BuildContext context) { + return Container( + color: const Color(0xFF1E1E1E), + padding: const EdgeInsets.symmetric(horizontal: 16, vertical: 10), + child: Row( + children: [ + Expanded( + child: OutlinedButton.icon( + onPressed: onPull, + icon: const Icon(Icons.download_outlined, size: 16), + label: const Text('Pull'), + ), + ), + const SizedBox(width: 8), + Expanded( + child: ElevatedButton.icon( + onPressed: onCommit, + icon: const Icon(Icons.commit, size: 16), + label: const Text('Commit'), + ), + ), + const SizedBox(width: 8), + Expanded( + child: OutlinedButton.icon( + onPressed: onPush, + icon: const Icon(Icons.upload_outlined, size: 16), + label: const Text('Push'), + ), + ), + ], + ), + ); + } +} diff --git a/apps/mobile/lib/features/git/presentation/widgets/file_change_tile.dart b/apps/mobile/lib/features/git/presentation/widgets/file_change_tile.dart new file mode 100644 index 0000000..144a6d4 --- /dev/null +++ b/apps/mobile/lib/features/git/presentation/widgets/file_change_tile.dart @@ -0,0 +1,93 @@ +import 'package:flutter/material.dart'; + +import '../../../../core/models/git_models.dart'; + +/// A list tile for a single [GitFileChange]. +class FileChangeTile extends StatelessWidget { + final GitFileChange change; + final VoidCallback? onTap; + + const FileChangeTile({ + super.key, + required this.change, + this.onTap, + }); + + String _statusLabel(FileChangeStatus status) { + return switch (status) { + FileChangeStatus.modified => 'M', + FileChangeStatus.added => 'A', + FileChangeStatus.deleted => 'D', + FileChangeStatus.renamed => 'R', + FileChangeStatus.untracked => '?', + }; + } + + Color _statusColor(FileChangeStatus status) { + return switch (status) { + FileChangeStatus.modified => const Color(0xFF569CD6), + FileChangeStatus.added => const Color(0xFF4EC9B0), + FileChangeStatus.deleted => const Color(0xFFF44747), + FileChangeStatus.renamed => const Color(0xFFFF9800), + FileChangeStatus.untracked => const Color(0xFF9E9E9E), + }; + } + + @override + Widget build(BuildContext context) { + final color = _statusColor(change.status); + final label = _statusLabel(change.status); + + final hasStats = + change.additions != null || change.deletions != null; + + return ListTile( + onTap: onTap, + dense: true, + leading: Container( + width: 22, + height: 22, + decoration: BoxDecoration( + color: color.withOpacity(0.15), + borderRadius: BorderRadius.circular(4), + border: Border.all(color: color.withOpacity(0.4)), + ), + alignment: Alignment.center, + child: Text( + label, + style: TextStyle( + fontSize: 12, + fontWeight: FontWeight.w700, + color: color, + ), + ), + ), + title: Text( + change.path, + style: const TextStyle( + fontSize: 13, + fontFamily: 'JetBrainsMono', + color: Color(0xFFD4D4D4), + ), + overflow: TextOverflow.ellipsis, + ), + subtitle: hasStats + ? Text( + [ + if (change.additions != null) '+${change.additions}', + if (change.deletions != null) '-${change.deletions}', + ].join(' '), + style: const TextStyle( + fontSize: 11, + fontFamily: 'JetBrainsMono', + color: Color(0xFF9E9E9E), + ), + ) + : null, + trailing: onTap != null + ? const Icon(Icons.chevron_right, + size: 18, color: Color(0xFF9E9E9E)) + : null, + ); + } +} diff --git a/apps/mobile/lib/features/git/presentation/widgets/git_status_card.dart b/apps/mobile/lib/features/git/presentation/widgets/git_status_card.dart new file mode 100644 index 0000000..0ffa484 --- /dev/null +++ b/apps/mobile/lib/features/git/presentation/widgets/git_status_card.dart @@ -0,0 +1,80 @@ +import 'package:flutter/material.dart'; + +import '../../../../core/models/git_models.dart'; + +/// Card showing branch name, ahead/behind chip counts, and a clean/dirty badge. +class GitStatusCard extends StatelessWidget { + final GitStatus status; + + const GitStatusCard({super.key, required this.status}); + + @override + Widget build(BuildContext context) { + return Card( + margin: const EdgeInsets.all(12), + child: Padding( + padding: const EdgeInsets.symmetric(horizontal: 16, vertical: 12), + child: Row( + children: [ + const Icon(Icons.account_tree_outlined, + size: 18, color: Color(0xFF569CD6)), + const SizedBox(width: 8), + Expanded( + child: Text( + status.branch, + style: const TextStyle( + fontSize: 14, + fontWeight: FontWeight.w600, + color: Color(0xFFD4D4D4), + ), + ), + ), + if (status.ahead > 0) ...[ + _Chip( + label: '↑ ${status.ahead}', + color: const Color(0xFF4EC9B0), + ), + const SizedBox(width: 6), + ], + if (status.behind > 0) ...[ + _Chip( + label: '↓ ${status.behind}', + color: const Color(0xFFFF9800), + ), + const SizedBox(width: 6), + ], + _Chip( + label: status.isClean ? 'Clean' : 'Dirty', + color: status.isClean + ? const Color(0xFF4CAF50) + : const Color(0xFFF44747), + ), + ], + ), + ), + ); + } +} + +class _Chip extends StatelessWidget { + final String label; + final Color color; + + const _Chip({required this.label, required this.color}); + + @override + Widget build(BuildContext context) { + return Container( + padding: const EdgeInsets.symmetric(horizontal: 8, vertical: 3), + decoration: BoxDecoration( + color: color.withOpacity(0.15), + borderRadius: BorderRadius.circular(4), + border: Border.all(color: color.withOpacity(0.4)), + ), + child: Text( + label, + style: TextStyle(fontSize: 11, color: color, fontWeight: FontWeight.w500), + ), + ); + } +} diff --git a/apps/mobile/lib/features/home/home_shell.dart b/apps/mobile/lib/features/home/home_shell.dart new file mode 100644 index 0000000..4c58b53 --- /dev/null +++ b/apps/mobile/lib/features/home/home_shell.dart @@ -0,0 +1,122 @@ +import 'package:flutter/material.dart'; +import 'package:flutter_riverpod/flutter_riverpod.dart'; +import 'package:go_router/go_router.dart'; + +import '../../core/network/connection_state.dart' as cs; +import '../../core/providers/websocket_provider.dart'; +import '../approvals/domain/providers/approval_provider.dart'; + +/// Root shell widget that wraps the bottom-navigation branches. +/// +/// Renders a [ConnectionStatusBar] overlaid at the top of the body, and a +/// [BottomNavigationBar] with badge support for pending approvals. +class HomeShell extends ConsumerWidget { + final StatefulNavigationShell navigationShell; + + const HomeShell({super.key, required this.navigationShell}); + + @override + Widget build(BuildContext context, WidgetRef ref) { + final pendingCount = ref.watch(pendingApprovalsProvider).length; + + return Scaffold( + body: Stack( + children: [ + // Main content + navigationShell, + // Connection status overlay at top + const Positioned( + top: 0, + left: 0, + right: 0, + child: _ConnectionStatusBar(), + ), + ], + ), + bottomNavigationBar: BottomNavigationBar( + currentIndex: navigationShell.currentIndex, + type: BottomNavigationBarType.fixed, + items: [ + const BottomNavigationBarItem( + icon: Icon(Icons.chat_bubble_outline), + label: 'Chat', + ), + const BottomNavigationBarItem( + icon: Icon(Icons.difference_outlined), + label: 'Diff', + ), + const BottomNavigationBarItem( + icon: Icon(Icons.folder_outlined), + label: 'Files', + ), + const BottomNavigationBarItem( + icon: Icon(Icons.source_outlined), + label: 'Git', + ), + BottomNavigationBarItem( + icon: Badge( + isLabelVisible: pendingCount > 0, + label: Text('$pendingCount'), + child: const Icon(Icons.checklist_outlined), + ), + label: 'Approvals', + ), + const BottomNavigationBarItem( + icon: Icon(Icons.settings_outlined), + label: 'Settings', + ), + ], + onTap: (index) => navigationShell.goBranch( + index, + initialLocation: index == navigationShell.currentIndex, + ), + ), + ); + } +} + +// --------------------------------------------------------------------------- +// Connection status bar +// --------------------------------------------------------------------------- + +class _ConnectionStatusBar extends ConsumerWidget { + const _ConnectionStatusBar(); + + @override + Widget build(BuildContext context, WidgetRef ref) { + final statusAsync = ref.watch(connectionStatusProvider); + return statusAsync.when( + data: (status) => _bar(status), + loading: () => const SizedBox.shrink(), + error: (_, __) => const SizedBox.shrink(), + ); + } + + Widget _bar(cs.ConnectionStatus status) { + if (status == cs.ConnectionStatus.connected) return const SizedBox.shrink(); + + final isReconnecting = status == cs.ConnectionStatus.reconnecting; + final color = isReconnecting + ? const Color(0xFFFF9800) + : const Color(0xFFF44747); + final message = isReconnecting ? 'Reconnecting…' : 'Offline'; + + return Material( + color: Colors.transparent, + child: Container( + width: double.infinity, + color: color, + padding: const EdgeInsets.symmetric(vertical: 3), + child: Text( + message, + textAlign: TextAlign.center, + style: const TextStyle( + color: Colors.white, + fontSize: 12, + fontWeight: FontWeight.w500, + ), + ), + ), + ); + } +} diff --git a/apps/mobile/lib/features/repos/domain/providers/repo_provider.dart b/apps/mobile/lib/features/repos/domain/providers/repo_provider.dart new file mode 100644 index 0000000..6947540 --- /dev/null +++ b/apps/mobile/lib/features/repos/domain/providers/repo_provider.dart @@ -0,0 +1,239 @@ +import 'dart:async'; + +import 'package:flutter_riverpod/flutter_riverpod.dart'; + +import '../../../../core/models/file_models.dart'; +import '../../../../core/network/websocket_messages.dart'; +import '../../../../core/network/websocket_service.dart'; +import '../../../../core/providers/websocket_provider.dart'; + +// --------------------------------------------------------------------------- +// State +// --------------------------------------------------------------------------- + +class RepoState { + final String currentPath; + final List nodes; + final bool isLoading; + final String? error; + final bool showHidden; + + const RepoState({ + this.currentPath = '.', + this.nodes = const [], + this.isLoading = false, + this.error, + this.showHidden = false, + }); + + RepoState copyWith({ + String? currentPath, + List? nodes, + bool? isLoading, + String? error, + bool? showHidden, + bool clearError = false, + }) { + return RepoState( + currentPath: currentPath ?? this.currentPath, + nodes: nodes ?? this.nodes, + isLoading: isLoading ?? this.isLoading, + error: clearError ? null : (error ?? this.error), + showHidden: showHidden ?? this.showHidden, + ); + } + + /// Path segments for breadcrumb display. + List get breadcrumbs { + if (currentPath == '.' || currentPath == '/') return ['/']; + final normalised = currentPath.replaceAll('\\', '/'); + final parts = normalised.split('/').where((s) => s.isNotEmpty).toList(); + return ['/', ...parts]; + } + + /// Visible nodes, filtered by [showHidden]. + List get visibleNodes { + if (showHidden) return nodes; + return nodes.where((n) => !n.name.startsWith('.')).toList(); + } + + bool get isAtRoot { + return currentPath == '.' || currentPath == '/' || currentPath.isEmpty; + } +} + +// --------------------------------------------------------------------------- +// Notifier +// --------------------------------------------------------------------------- + +class RepoNotifier extends FamilyAsyncNotifier { + /// The sessionId passed as the family argument. + String get _sessionId => arg; + + @override + Future build(String arg) async { + // Listen to inbound bridge messages and surface file_list / file_read + // responses to waiting completers. + ref.listen>(bridgeMessagesProvider, (_, next) { + next.whenData(_handleMessage); + }); + + // Start at root of session working directory. + final initial = const RepoState(); + await _fetchDirectory(initial.currentPath); + return state.value ?? initial; + } + + // --------------------------------------------------------------------------- + // Response correlators + // --------------------------------------------------------------------------- + + final Map> _pending = {}; + + void _handleMessage(BridgeMessage msg) { + if (msg.id != null && _pending.containsKey(msg.id)) { + _pending[msg.id]!.complete(msg); + _pending.remove(msg.id); + return; + } + // Unsolicited file_list_response — ignore (another session may have sent). + } + + Future _sendAndAwait(BridgeMessage outgoing) { + final completer = Completer(); + if (outgoing.id != null) { + _pending[outgoing.id!] = completer; + } + final service = ref.read(webSocketServiceProvider); + service.send(outgoing); + + // 30-second timeout to avoid leaking completers. + Future.delayed(const Duration(seconds: 30), () { + if (!completer.isCompleted) { + _pending.remove(outgoing.id); + completer.completeError(TimeoutException('Bridge response timed out')); + } + }); + + return completer.future; + } + + // --------------------------------------------------------------------------- + // Public actions + // --------------------------------------------------------------------------- + + /// Fetch [path] and update state with the returned nodes. + Future fetchDirectory(String path) async { + final current = state.value ?? const RepoState(); + state = AsyncData(current.copyWith(isLoading: true, clearError: true)); + await _fetchDirectory(path); + } + + Future _fetchDirectory(String path) async { + final current = state.value ?? const RepoState(); + try { + final outgoing = BridgeMessage.fileList( + sessionId: _sessionId, + path: path, + ); + final response = await _sendAndAwait(outgoing); + + if (response.type == BridgeMessageType.error) { + final msg = response.payload['message'] as String? ?? 'Unknown error'; + state = AsyncData( + current.copyWith( + isLoading: false, + error: msg, + currentPath: path, + ), + ); + return; + } + + final rawNodes = response.payload['nodes'] as List? ?? []; + final nodes = rawNodes + .whereType>() + .map(FileTreeNode.fromJson) + .toList(); + + // Sort: directories first, then files, each group alphabetically. + nodes.sort((a, b) { + if (a.type != b.type) { + return a.type == FileNodeType.directory ? -1 : 1; + } + return a.name.toLowerCase().compareTo(b.name.toLowerCase()); + }); + + state = AsyncData( + current.copyWith( + currentPath: path, + nodes: nodes, + isLoading: false, + clearError: true, + ), + ); + } catch (e) { + state = AsyncData( + current.copyWith( + isLoading: false, + error: e.toString(), + ), + ); + } + } + + /// Fetch the content of a file at [path]. + Future readFile(String path) async { + final outgoing = BridgeMessage.fileRead( + sessionId: _sessionId, + path: path, + ); + final response = await _sendAndAwait(outgoing); + if (response.type == BridgeMessageType.error) { + final msg = response.payload['message'] as String? ?? 'Unknown error'; + throw Exception(msg); + } + return response.payload['content'] as String? ?? ''; + } + + /// Navigate to [path], updating the current directory. + Future navigateTo(String path) => fetchDirectory(path); + + /// Navigate to the parent directory. + Future navigateUp() { + final current = state.value?.currentPath ?? '.'; + if (current == '.' || current == '/' || current.isEmpty) return Future.value(); + + final normalised = current.replaceAll('\\', '/'); + final segments = normalised.split('/').where((s) => s.isNotEmpty).toList(); + if (segments.isEmpty) return Future.value(); + segments.removeLast(); + final parent = segments.isEmpty ? '/' : segments.join('/'); + return fetchDirectory(parent); + } + + /// Toggle display of hidden (dot-prefixed) files. + void toggleHidden() { + final current = state.value ?? const RepoState(); + state = AsyncData(current.copyWith(showHidden: !current.showHidden)); + } +} + +// --------------------------------------------------------------------------- +// Providers +// --------------------------------------------------------------------------- + +/// Family notifier provider keyed by sessionId. +final repoProvider = + AsyncNotifierProviderFamily( + RepoNotifier.new, +); + +/// Provides the content string of a file at [path] for a given [sessionId]. +final fileContentProvider = + FutureProviderFamily( + (ref, args) async { + final notifier = ref.read(repoProvider(args.sessionId).notifier); + return notifier.readFile(args.path); + }, +); diff --git a/apps/mobile/lib/features/repos/presentation/screens/file_tree_screen.dart b/apps/mobile/lib/features/repos/presentation/screens/file_tree_screen.dart new file mode 100644 index 0000000..3f3ec5b --- /dev/null +++ b/apps/mobile/lib/features/repos/presentation/screens/file_tree_screen.dart @@ -0,0 +1,152 @@ +import 'package:flutter/material.dart'; +import 'package:flutter_riverpod/flutter_riverpod.dart'; +import 'package:go_router/go_router.dart'; + +import '../../../../core/models/file_models.dart'; +import '../../../../shared/widgets/empty_state.dart'; +import '../../../../shared/widgets/error_card.dart'; +import '../../../../shared/widgets/loading_indicator.dart'; +import '../../domain/providers/repo_provider.dart'; +import '../widgets/breadcrumb_nav.dart'; +import '../widgets/file_tree_node_widget.dart'; + +/// Full-screen file tree browser for a given [sessionId]. +class FileTreeScreen extends ConsumerWidget { + final String sessionId; + + const FileTreeScreen({super.key, required this.sessionId}); + + @override + Widget build(BuildContext context, WidgetRef ref) { + final repoAsync = ref.watch(repoProvider(sessionId)); + final notifier = ref.read(repoProvider(sessionId).notifier); + + return repoAsync.when( + loading: () => Scaffold( + appBar: _buildAppBar(context, ref, '…', notifier), + body: const LoadingIndicator(message: 'Loading directory…'), + ), + error: (err, _) => Scaffold( + appBar: _buildAppBar(context, ref, 'Error', notifier), + body: Center( + child: ErrorCard( + message: err.toString(), + onRetry: () => notifier.fetchDirectory( + repoAsync.value?.currentPath ?? '.', + ), + ), + ), + ), + data: (state) { + final nodes = state.visibleNodes; + + return Scaffold( + backgroundColor: const Color(0xFF121212), + appBar: _buildAppBar(context, ref, state.currentPath, notifier), + floatingActionButton: FloatingActionButton.small( + tooltip: state.showHidden ? 'Hide hidden files' : 'Show hidden files', + onPressed: notifier.toggleHidden, + child: Icon( + state.showHidden + ? Icons.visibility_off_outlined + : Icons.visibility_outlined, + ), + ), + body: Column( + children: [ + // Breadcrumb + Container( + color: const Color(0xFF1E1E1E), + child: BreadcrumbNav( + path: state.currentPath, + onSegmentTap: notifier.navigateTo, + ), + ), + const Divider(height: 1, color: Color(0xFF3E3E3E)), + // Loading overlay when fetching a sub-directory + if (state.isLoading) + const LinearProgressIndicator(minHeight: 2), + // Error banner + if (state.error != null) + Padding( + padding: const EdgeInsets.all(8), + child: ErrorCard( + message: state.error!, + onRetry: () => notifier.fetchDirectory(state.currentPath), + ), + ), + // File list + Expanded( + child: nodes.isEmpty && !state.isLoading + ? EmptyState( + icon: Icons.folder_open, + title: 'Empty directory', + subtitle: state.showHidden + ? null + : 'Toggle visibility to show hidden files.', + ) + : RefreshIndicator( + onRefresh: () => + notifier.fetchDirectory(state.currentPath), + child: ListView.builder( + itemCount: nodes.length, + itemBuilder: (context, index) { + final node = nodes[index]; + return FileTreeNodeWidget( + node: node, + onTap: () => _onNodeTap(context, node), + ); + }, + ), + ), + ), + ], + ), + ); + }, + ); + } + + AppBar _buildAppBar( + BuildContext context, + WidgetRef ref, + String currentPath, + RepoNotifier notifier, + ) { + final state = ref.read(repoProvider(sessionId)).value; + final atRoot = state?.isAtRoot ?? true; + + return AppBar( + backgroundColor: const Color(0xFF1E1E1E), + leading: atRoot + ? null + : IconButton( + icon: const Icon(Icons.arrow_back), + onPressed: notifier.navigateUp, + ), + title: Text( + currentPath, + style: const TextStyle( + fontFamily: 'JetBrainsMono', + fontSize: 13, + color: Color(0xFFD4D4D4), + ), + overflow: TextOverflow.ellipsis, + ), + ); + } + + void _onNodeTap(BuildContext context, FileTreeNode node) { + final notifier = + // ignore: invalid_use_of_protected_member + ProviderScope.containerOf(context).read(repoProvider(sessionId).notifier); + if (node.type == FileNodeType.directory) { + notifier.navigateTo(node.path); + } else { + context.push( + '/home/repos/view', + extra: {'path': node.path, 'sessionId': sessionId}, + ); + } + } +} diff --git a/apps/mobile/lib/features/repos/presentation/screens/file_viewer_screen.dart b/apps/mobile/lib/features/repos/presentation/screens/file_viewer_screen.dart new file mode 100644 index 0000000..2616fa3 --- /dev/null +++ b/apps/mobile/lib/features/repos/presentation/screens/file_viewer_screen.dart @@ -0,0 +1,172 @@ +import 'package:flutter/material.dart'; +import 'package:flutter/services.dart'; +import 'package:flutter_riverpod/flutter_riverpod.dart'; + +import '../../../../shared/widgets/error_card.dart'; +import '../../../../shared/widgets/loading_indicator.dart'; +import '../../domain/providers/repo_provider.dart'; +import '../widgets/syntax_highlighted_file.dart'; + +/// Displays the content of a single file fetched via the bridge. +class FileViewerScreen extends ConsumerWidget { + final String sessionId; + final String path; + + const FileViewerScreen({ + super.key, + required this.sessionId, + required this.path, + }); + + String get _filename { + final normalised = path.replaceAll('\\', '/'); + return normalised.split('/').last; + } + + int? _fileSizeFromState(WidgetRef ref) { + final state = ref.read(repoProvider(sessionId)).value; + if (state == null) return null; + try { + return state.nodes + .firstWhere((n) => n.path == path) + .size; + } catch (_) { + return null; + } + } + + String _formatSize(int bytes) { + if (bytes < 1024) return '$bytes B'; + if (bytes < 1024 * 1024) { + final kb = bytes / 1024; + return '${kb.toStringAsFixed(kb < 10 ? 1 : 0)} KB'; + } + final mb = bytes / (1024 * 1024); + return '${mb.toStringAsFixed(mb < 10 ? 1 : 0)} MB'; + } + + @override + Widget build(BuildContext context, WidgetRef ref) { + final contentAsync = ref.watch( + fileContentProvider((sessionId: sessionId, path: path)), + ); + final knownSize = _fileSizeFromState(ref); + + return Scaffold( + backgroundColor: const Color(0xFF121212), + appBar: AppBar( + backgroundColor: const Color(0xFF1E1E1E), + title: Row( + children: [ + Expanded( + child: Text( + _filename, + style: const TextStyle( + fontFamily: 'JetBrainsMono', + fontSize: 13, + color: Color(0xFFD4D4D4), + ), + overflow: TextOverflow.ellipsis, + ), + ), + if (knownSize != null) ...[ + const SizedBox(width: 8), + Container( + padding: const EdgeInsets.symmetric( + horizontal: 8, + vertical: 3, + ), + decoration: BoxDecoration( + color: const Color(0xFF2D2D2D), + borderRadius: BorderRadius.circular(4), + ), + child: Text( + _formatSize(knownSize), + style: const TextStyle( + fontSize: 11, + color: Color(0xFF9E9E9E), + fontFamily: 'JetBrainsMono', + ), + ), + ), + ], + ], + ), + actions: [ + contentAsync.whenOrNull( + data: (content) => IconButton( + tooltip: 'Copy file', + icon: const Icon(Icons.copy_outlined), + onPressed: () async { + await Clipboard.setData(ClipboardData(text: content)); + if (context.mounted) { + ScaffoldMessenger.of(context).showSnackBar( + const SnackBar( + content: Text('Copied to clipboard'), + duration: Duration(seconds: 2), + ), + ); + } + }, + ), + ) ?? + const SizedBox.shrink(), + ], + ), + body: contentAsync.when( + loading: () => + const LoadingIndicator(message: 'Fetching file content…'), + error: (err, _) => Center( + child: Padding( + padding: const EdgeInsets.all(16), + child: ErrorCard( + message: err.toString(), + onRetry: () => ref.invalidate( + fileContentProvider((sessionId: sessionId, path: path)), + ), + ), + ), + ), + data: (content) { + final lineCount = '\n'.allMatches(content).length + 1; + return Column( + crossAxisAlignment: CrossAxisAlignment.stretch, + children: [ + if (lineCount > 1000) + Container( + color: const Color(0xFF2D2D2D), + padding: const EdgeInsets.symmetric( + horizontal: 12, + vertical: 6, + ), + child: Row( + children: [ + const Icon( + Icons.warning_amber_rounded, + size: 14, + color: Color(0xFFFF9800), + ), + const SizedBox(width: 6), + Text( + 'Large file — $lineCount lines.', + style: const TextStyle( + fontSize: 11, + color: Color(0xFFFF9800), + ), + ), + ], + ), + ), + Expanded( + child: SyntaxHighlightedFile( + content: content, + filePath: path, + ), + ), + ], + ); + }, + ), + ); + } +} diff --git a/apps/mobile/lib/features/repos/presentation/widgets/breadcrumb_nav.dart b/apps/mobile/lib/features/repos/presentation/widgets/breadcrumb_nav.dart new file mode 100644 index 0000000..ff7e0d5 --- /dev/null +++ b/apps/mobile/lib/features/repos/presentation/widgets/breadcrumb_nav.dart @@ -0,0 +1,125 @@ +import 'package:flutter/material.dart'; + +import '../../../../shared/constants/colors.dart'; + +/// Horizontal scrollable breadcrumb navigation for a file path. +/// +/// [path] is split on `/` and `\` into segments. Each segment is rendered as +/// a tappable [TextButton]. Tapping a segment calls [onSegmentTap] with the +/// cumulative path up to and including that segment. The last (current) +/// segment is rendered in bold primary colour. Adjacent segments are separated +/// by a small chevron icon. The row auto-scrolls to the trailing end whenever +/// [path] changes. +class BreadcrumbNav extends StatefulWidget { + final String path; + final void Function(String path) onSegmentTap; + + const BreadcrumbNav({ + super.key, + required this.path, + required this.onSegmentTap, + }); + + @override + State createState() => _BreadcrumbNavState(); +} + +class _BreadcrumbNavState extends State { + final _scrollController = ScrollController(); + + @override + void didUpdateWidget(BreadcrumbNav oldWidget) { + super.didUpdateWidget(oldWidget); + if (oldWidget.path != widget.path) { + // Scroll to the end after layout completes. + WidgetsBinding.instance.addPostFrameCallback((_) { + if (_scrollController.hasClients) { + _scrollController.animateTo( + _scrollController.position.maxScrollExtent, + duration: const Duration(milliseconds: 200), + curve: Curves.easeOut, + ); + } + }); + } + } + + @override + void dispose() { + _scrollController.dispose(); + super.dispose(); + } + + List<_Segment> _buildSegments(String path) { + final normalised = path.replaceAll('\\', '/'); + final parts = normalised.split('/').where((s) => s.isNotEmpty).toList(); + + final segments = <_Segment>[]; + // Root segment. + segments.add(_Segment(label: '/', cumulativePath: '/')); + + for (var i = 0; i < parts.length; i++) { + final cumulative = '/${parts.sublist(0, i + 1).join('/')}'; + segments.add(_Segment(label: parts[i], cumulativePath: cumulative)); + } + + return segments; + } + + @override + Widget build(BuildContext context) { + final segments = _buildSegments(widget.path); + final lastIndex = segments.length - 1; + + return SizedBox( + height: 40, + child: ListView.builder( + controller: _scrollController, + scrollDirection: Axis.horizontal, + itemCount: segments.length * 2 - 1, + padding: const EdgeInsets.symmetric(horizontal: 4), + itemBuilder: (context, index) { + // Even indices → segment buttons, odd indices → separators. + if (index.isOdd) { + return const Icon( + Icons.chevron_right, + size: 16, + color: Color(0xFF9E9E9E), + ); + } + final segIndex = index ~/ 2; + final seg = segments[segIndex]; + final isCurrent = segIndex == lastIndex; + + return TextButton.icon( + onPressed: () => widget.onSegmentTap(seg.cumulativePath), + style: TextButton.styleFrom( + padding: const EdgeInsets.symmetric(horizontal: 6), + minimumSize: Size.zero, + tapTargetSize: MaterialTapTargetSize.shrinkWrap, + ), + icon: segIndex == 0 + ? const Icon(Icons.folder, size: 14, color: kTextSecondary) + : const SizedBox.shrink(), + label: Text( + seg.label, + style: TextStyle( + fontSize: 13, + fontWeight: + isCurrent ? FontWeight.w700 : FontWeight.w400, + color: isCurrent ? kPrimary : kTextSecondary, + ), + ), + ); + }, + ), + ); + } +} + +class _Segment { + final String label; + final String cumulativePath; + + const _Segment({required this.label, required this.cumulativePath}); +} diff --git a/apps/mobile/lib/features/repos/presentation/widgets/file_tree_node_widget.dart b/apps/mobile/lib/features/repos/presentation/widgets/file_tree_node_widget.dart new file mode 100644 index 0000000..8985acb --- /dev/null +++ b/apps/mobile/lib/features/repos/presentation/widgets/file_tree_node_widget.dart @@ -0,0 +1,133 @@ +import 'package:flutter/material.dart'; + +import '../../../../core/models/file_models.dart'; +import '../../../../shared/constants/colors.dart'; +import '../../../../shared/constants/typography.dart'; + +/// A single row in the file tree list. +/// +/// Shows an appropriate icon and colour for the node type/extension, the +/// node name in monospace, and — for files — a human-readable size badge. +class FileTreeNodeWidget extends StatelessWidget { + final FileTreeNode node; + final VoidCallback onTap; + + const FileTreeNodeWidget({ + super.key, + required this.node, + required this.onTap, + }); + + // --------------------------------------------------------------------------- + // Icon helpers + // --------------------------------------------------------------------------- + + static IconData _iconForNode(FileTreeNode node) { + if (node.type == FileNodeType.directory) return Icons.folder; + final ext = _extension(node.name); + return switch (ext) { + 'dart' => Icons.code, + 'ts' || 'tsx' || 'js' || 'jsx' => Icons.javascript, + 'md' || 'mdx' => Icons.description, + 'json' => Icons.data_object, + 'yaml' || 'yml' => Icons.settings, + 'png' || 'jpg' || 'jpeg' || 'gif' || 'svg' || 'webp' => Icons.image, + _ => Icons.insert_drive_file, + }; + } + + static Color _colorForNode(FileTreeNode node) { + if (node.type == FileNodeType.directory) { + return const Color(0xFFE8C17A); // warm yellow for folders + } + final ext = _extension(node.name); + return switch (ext) { + 'dart' => kPrimary, // blue + 'ts' || 'tsx' || 'js' || 'jsx' => const Color(0xFFE8C17A), // yellow + 'md' || 'mdx' => const Color(0xFF4EC9B0), // teal + 'json' || 'yaml' || 'yml' || 'toml' || 'ini' => kTextSecondary, // grey + _ => kTextSecondary, + }; + } + + static String _extension(String name) { + final dot = name.lastIndexOf('.'); + if (dot == -1 || dot == name.length - 1) return ''; + return name.substring(dot + 1).toLowerCase(); + } + + // --------------------------------------------------------------------------- + // Size formatting + // --------------------------------------------------------------------------- + + static String _formatSize(int bytes) { + if (bytes < 1024) return '${bytes} B'; + if (bytes < 1024 * 1024) { + final kb = bytes / 1024; + return '${kb.toStringAsFixed(kb < 10 ? 1 : 0)} KB'; + } + final mb = bytes / (1024 * 1024); + return '${mb.toStringAsFixed(mb < 10 ? 1 : 0)} MB'; + } + + // --------------------------------------------------------------------------- + // Build + // --------------------------------------------------------------------------- + + @override + Widget build(BuildContext context) { + final isDir = node.type == FileNodeType.directory; + final iconColor = _colorForNode(node); + final icon = _iconForNode(node); + + return Column( + mainAxisSize: MainAxisSize.min, + children: [ + ListTile( + dense: true, + leading: Icon(icon, color: iconColor, size: 20), + title: Text( + node.name, + style: AppTypography.code.copyWith( + fontSize: 13, + color: const Color(0xFFD4D4D4), + ), + overflow: TextOverflow.ellipsis, + ), + trailing: Row( + mainAxisSize: MainAxisSize.min, + children: [ + if (!isDir && node.size != null) + Container( + padding: const EdgeInsets.symmetric( + horizontal: 6, + vertical: 2, + ), + decoration: BoxDecoration( + color: const Color(0xFF2D2D2D), + borderRadius: BorderRadius.circular(4), + ), + child: Text( + _formatSize(node.size!), + style: const TextStyle( + fontSize: 10, + color: Color(0xFF9E9E9E), + fontFamily: 'JetBrainsMono', + ), + ), + ), + const SizedBox(width: 4), + const Icon( + Icons.chevron_right, + size: 16, + color: Color(0xFF9E9E9E), + ), + ], + ), + onTap: onTap, + ), + const Divider(height: 1, thickness: 1, color: Color(0xFF2A2A2A)), + ], + ); + } +} diff --git a/apps/mobile/lib/features/repos/presentation/widgets/syntax_highlighted_file.dart b/apps/mobile/lib/features/repos/presentation/widgets/syntax_highlighted_file.dart new file mode 100644 index 0000000..69f1dfc --- /dev/null +++ b/apps/mobile/lib/features/repos/presentation/widgets/syntax_highlighted_file.dart @@ -0,0 +1,387 @@ +import 'package:flutter/material.dart'; +import 'package:flutter/services.dart'; + +import '../../../../shared/constants/typography.dart'; + +// --------------------------------------------------------------------------- +// Syntax colour constants (VS Code Dark+ palette) +// --------------------------------------------------------------------------- + +const _colDefault = Color(0xFFD4D4D4); +const _colKeyword = Color(0xFF569CD6); +const _colString = Color(0xFFCE9178); +const _colComment = Color(0xFF6A9955); +const _colNumber = Color(0xFFB5CEA8); +const _colType = Color(0xFF4EC9B0); + +// --------------------------------------------------------------------------- +// Token model +// --------------------------------------------------------------------------- + +enum _TokenKind { comment, string, keyword, number, type, plain } + +class _Token { + final String text; + final _TokenKind kind; + + const _Token(this.text, this.kind); + + Color get color => switch (kind) { + _TokenKind.comment => _colComment, + _TokenKind.string => _colString, + _TokenKind.keyword => _colKeyword, + _TokenKind.number => _colNumber, + _TokenKind.type => _colType, + _TokenKind.plain => _colDefault, + }; +} + +// --------------------------------------------------------------------------- +// Tokenizer +// --------------------------------------------------------------------------- + +const _dartKeywords = { + 'if', 'else', 'for', 'while', 'do', 'switch', 'case', 'break', 'continue', + 'return', 'class', 'extends', 'implements', 'mixin', 'with', 'abstract', + 'import', 'export', 'const', 'final', 'var', 'late', 'required', 'async', + 'await', 'yield', 'try', 'catch', 'finally', 'throw', 'new', 'void', + 'null', 'true', 'false', 'this', 'super', 'static', 'enum', 'typedef', + 'get', 'set', 'in', 'is', 'as', 'part', 'library', 'show', 'hide', +}; + +const _jsKeywords = { + 'if', 'else', 'for', 'while', 'do', 'switch', 'case', 'break', 'continue', + 'return', 'class', 'extends', 'import', 'export', 'const', 'let', 'var', + 'function', 'async', 'await', 'try', 'catch', 'finally', 'throw', 'new', + 'void', 'null', 'true', 'false', 'this', 'super', 'static', 'typeof', + 'instanceof', 'in', 'of', 'from', 'default', 'yield', +}; + +bool _isSyntaxLanguage(String ext) => + ext == 'dart' || ext == 'ts' || ext == 'tsx' || ext == 'js' || ext == 'jsx'; + +String _ext(String filePath) { + final dot = filePath.lastIndexOf('.'); + if (dot == -1 || dot == filePath.length - 1) return ''; + return filePath.substring(dot + 1).toLowerCase(); +} + +List<_Token> _tokeniseLine(String line, String ext) { + if (!_isSyntaxLanguage(ext)) return [_Token(line, _TokenKind.plain)]; + + final keywords = ext == 'dart' ? _dartKeywords : _jsKeywords; + final tokens = <_Token>[]; + + // State machine — process character by character. + var i = 0; + final buf = StringBuffer(); + + void flush({_TokenKind kind = _TokenKind.plain}) { + if (buf.isEmpty) return; + tokens.add(_Token(buf.toString(), kind)); + buf.clear(); + } + + while (i < line.length) { + // Single-line comment // + if (i + 1 < line.length && line[i] == '/' && line[i + 1] == '/') { + flush(); + tokens.add(_Token(line.substring(i), _TokenKind.comment)); + return tokens; + } + + // Block comment start /* (treat rest of line as comment for simplicity) + if (i + 1 < line.length && line[i] == '/' && line[i + 1] == '*') { + flush(); + final end = line.indexOf('*/', i + 2); + if (end == -1) { + tokens.add(_Token(line.substring(i), _TokenKind.comment)); + return tokens; + } + tokens.add(_Token(line.substring(i, end + 2), _TokenKind.comment)); + i = end + 2; + continue; + } + + // String literals " or ' + if (line[i] == '"' || line[i] == "'") { + flush(); + final quote = line[i]; + final sb = StringBuffer(quote); + i++; + while (i < line.length) { + if (line[i] == '\\' && i + 1 < line.length) { + sb.write(line[i]); + sb.write(line[i + 1]); + i += 2; + continue; + } + sb.write(line[i]); + if (line[i] == quote) { + i++; + break; + } + i++; + } + tokens.add(_Token(sb.toString(), _TokenKind.string)); + continue; + } + + // Template literal ` + if (line[i] == '`') { + flush(); + final end = line.indexOf('`', i + 1); + final close = end == -1 ? line.length : end + 1; + tokens.add(_Token(line.substring(i, close), _TokenKind.string)); + i = close; + continue; + } + + // Number literal + if (line[i].codeUnitAt(0) >= 48 && line[i].codeUnitAt(0) <= 57) { + flush(); + final start = i; + while (i < line.length && + (RegExp(r'[0-9._xXa-fA-F]').hasMatch(line[i]))) { + i++; + } + tokens.add(_Token(line.substring(start, i), _TokenKind.number)); + continue; + } + + // Word (keyword, type, or identifier) + if (RegExp(r'[a-zA-Z_$]').hasMatch(line[i])) { + flush(); + final start = i; + while (i < line.length && RegExp(r'[\w$]').hasMatch(line[i])) { + i++; + } + final word = line.substring(start, i); + _TokenKind kind; + if (keywords.contains(word)) { + kind = _TokenKind.keyword; + } else if (word.isNotEmpty && + word[0].toUpperCase() == word[0] && + word[0] != word[0].toLowerCase()) { + kind = _TokenKind.type; + } else { + kind = _TokenKind.plain; + } + tokens.add(_Token(word, kind)); + continue; + } + + buf.write(line[i]); + i++; + } + + flush(); + return tokens; +} + +// --------------------------------------------------------------------------- +// Widget +// --------------------------------------------------------------------------- + +const int _pageSize = 500; + +/// Scrollable syntax-highlighted file viewer with a line-number gutter. +/// +/// For files over [_pageSize] lines the first page is shown with a +/// "Load more" button at the bottom. +class SyntaxHighlightedFile extends StatefulWidget { + final String content; + final String filePath; + + const SyntaxHighlightedFile({ + super.key, + required this.content, + required this.filePath, + }); + + @override + State createState() => _SyntaxHighlightedFileState(); +} + +class _SyntaxHighlightedFileState extends State { + late List _allLines; + late int _visibleCount; + + @override + void initState() { + super.initState(); + _init(); + } + + @override + void didUpdateWidget(SyntaxHighlightedFile old) { + super.didUpdateWidget(old); + if (old.content != widget.content || old.filePath != widget.filePath) { + _init(); + } + } + + void _init() { + _allLines = widget.content.split('\n'); + _visibleCount = _allLines.length.clamp(0, _pageSize); + } + + void _loadMore() { + setState(() { + _visibleCount = + (_visibleCount + _pageSize).clamp(0, _allLines.length); + }); + } + + Future _copyAll() async { + await Clipboard.setData(ClipboardData(text: widget.content)); + } + + @override + Widget build(BuildContext context) { + final ext = _ext(widget.filePath); + final totalLines = _allLines.length; + final gutterWidth = '$totalLines'.length * 9.0 + 12; + final showLargeWarning = totalLines > 1000 && _visibleCount <= _pageSize; + final hasMore = _visibleCount < totalLines; + + return Column( + crossAxisAlignment: CrossAxisAlignment.stretch, + children: [ + if (showLargeWarning) + Container( + color: const Color(0xFF2D2D2D), + padding: const EdgeInsets.symmetric(horizontal: 12, vertical: 6), + child: Row( + children: [ + const Icon( + Icons.warning_amber_rounded, + size: 14, + color: Color(0xFFFF9800), + ), + const SizedBox(width: 6), + Text( + 'Large file — $totalLines lines total, showing first $_visibleCount.', + style: const TextStyle( + fontSize: 11, + color: Color(0xFFFF9800), + ), + ), + ], + ), + ), + Expanded( + child: Scrollbar( + child: SingleChildScrollView( + scrollDirection: Axis.vertical, + child: SingleChildScrollView( + scrollDirection: Axis.horizontal, + child: IntrinsicWidth( + child: Column( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + // Code lines + for (var i = 0; i < _visibleCount; i++) + _CodeLine( + lineNumber: i + 1, + line: _allLines[i], + ext: ext, + gutterWidth: gutterWidth, + ), + // Load more button + if (hasMore) + Padding( + padding: const EdgeInsets.symmetric(vertical: 8), + child: Center( + child: TextButton.icon( + onPressed: _loadMore, + icon: const Icon(Icons.expand_more, size: 16), + label: Text( + 'Load more (${totalLines - _visibleCount} remaining)', + style: const TextStyle(fontSize: 12), + ), + ), + ), + ), + ], + ), + ), + ), + ), + ), + ), + ], + ); + } +} + +// --------------------------------------------------------------------------- +// Single code line +// --------------------------------------------------------------------------- + +class _CodeLine extends StatelessWidget { + final int lineNumber; + final String line; + final String ext; + final double gutterWidth; + + const _CodeLine({ + required this.lineNumber, + required this.line, + required this.ext, + required this.gutterWidth, + }); + + @override + Widget build(BuildContext context) { + final tokens = _tokeniseLine(line, ext); + + return Row( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + // Gutter + SizedBox( + width: gutterWidth, + child: Padding( + padding: const EdgeInsets.symmetric(horizontal: 4, vertical: 1), + child: Text( + '$lineNumber', + textAlign: TextAlign.right, + style: const TextStyle( + fontFamily: 'JetBrainsMono', + fontSize: 13, + color: Color(0xFF5A5A5A), + height: 1.5, + ), + ), + ), + ), + // Separator + Container( + width: 1, + color: const Color(0xFF2A2A2A), + margin: const EdgeInsets.symmetric(horizontal: 6, vertical: 1), + ), + // Code + Padding( + padding: const EdgeInsets.only(right: 16, top: 1, bottom: 1), + child: RichText( + text: TextSpan( + children: tokens + .map( + (t) => TextSpan( + text: t.text, + style: AppTypography.code.copyWith( + color: t.color, + height: 1.5, + ), + ), + ) + .toList(), + ), + ), + ), + ], + ); + } +} diff --git a/apps/mobile/lib/features/session/domain/providers/session_timeline_provider.dart b/apps/mobile/lib/features/session/domain/providers/session_timeline_provider.dart new file mode 100644 index 0000000..c80d7dc --- /dev/null +++ b/apps/mobile/lib/features/session/domain/providers/session_timeline_provider.dart @@ -0,0 +1,59 @@ +import 'package:flutter_riverpod/flutter_riverpod.dart'; + +import '../../../../core/models/session_models.dart'; +import '../../../../core/providers/database_provider.dart'; + +/// Derives a [List] from the messages stored for [sessionId]. +/// +/// - User messages → [SessionEventType.userMessage] +/// - Agent text messages → [SessionEventType.agentMessage] +/// - Tool-call messages → [SessionEventType.toolUse] +/// +/// Results are sorted by [SessionEvent.timestamp] ascending. +final sessionEventsProvider = + Provider.family, String>((ref, sessionId) { + final messagesAsync = ref.watch(_rawMessagesProvider(sessionId)); + final messages = messagesAsync.valueOrNull ?? []; + + final events = []; + + for (final msg in messages) { + final eventType = switch (msg.messageType) { + 'tool_call' => SessionEventType.toolUse, + _ => msg.role == 'user' + ? SessionEventType.userMessage + : SessionEventType.agentMessage, + }; + + final title = switch (eventType) { + SessionEventType.userMessage => 'User', + SessionEventType.agentMessage => 'Agent', + SessionEventType.toolUse => 'Tool Use', + _ => 'Event', + }; + + final description = msg.content.isNotEmpty + ? (msg.content.length > 120 + ? '${msg.content.substring(0, 120)}…' + : msg.content) + : null; + + events.add(SessionEvent( + id: '${sessionId}_${msg.id}', + sessionId: sessionId, + eventType: eventType, + title: title, + description: description, + timestamp: msg.createdAt, + )); + } + + events.sort((a, b) => a.timestamp.compareTo(b.timestamp)); + return events; +}); + +// Internal stream-backed provider for raw DB messages. +final _rawMessagesProvider = StreamProvider.family((ref, String sessionId) { + return ref.watch(databaseProvider).messageDao + .watchMessagesForSession(sessionId); +}); diff --git a/apps/mobile/lib/features/session/presentation/screens/session_detail_screen.dart b/apps/mobile/lib/features/session/presentation/screens/session_detail_screen.dart new file mode 100644 index 0000000..5b3db0f --- /dev/null +++ b/apps/mobile/lib/features/session/presentation/screens/session_detail_screen.dart @@ -0,0 +1,148 @@ +import 'package:flutter/material.dart'; +import 'package:flutter_riverpod/flutter_riverpod.dart'; + +import '../../../../core/models/session_models.dart'; +import '../../domain/providers/session_timeline_provider.dart'; +import '../widgets/session_timeline.dart'; + +/// Displays the detail view for a single [ChatSession]. +/// +/// Shows a stats row (message count, tool-use count, duration) at the top, +/// followed by the session [SessionTimeline]. +class SessionDetailScreen extends ConsumerWidget { + final String sessionId; + final String? sessionTitle; + + const SessionDetailScreen({ + super.key, + required this.sessionId, + this.sessionTitle, + }); + + @override + Widget build(BuildContext context, WidgetRef ref) { + final events = ref.watch(sessionEventsProvider(sessionId)); + + final messageCount = events + .where((e) => + e.eventType == SessionEventType.userMessage || + e.eventType == SessionEventType.agentMessage) + .length; + + final toolUseCount = + events.where((e) => e.eventType == SessionEventType.toolUse).length; + + Duration? duration; + if (events.isNotEmpty) { + duration = events.last.timestamp.difference(events.first.timestamp); + } + + final title = (sessionTitle != null && sessionTitle!.isNotEmpty) + ? sessionTitle! + : 'Session'; + + return Scaffold( + appBar: AppBar( + title: Text(title), + ), + body: Column( + children: [ + _StatsRow( + messageCount: messageCount, + toolUseCount: toolUseCount, + duration: duration, + ), + const Divider(height: 1), + Expanded( + child: SessionTimeline(events: events), + ), + ], + ), + ); + } +} + +class _StatsRow extends StatelessWidget { + final int messageCount; + final int toolUseCount; + final Duration? duration; + + const _StatsRow({ + required this.messageCount, + required this.toolUseCount, + required this.duration, + }); + + String _formatDuration(Duration d) { + if (d.inHours > 0) { + return '${d.inHours}h ${d.inMinutes.remainder(60)}m'; + } + if (d.inMinutes > 0) return '${d.inMinutes}m'; + return '${d.inSeconds}s'; + } + + @override + Widget build(BuildContext context) { + return Container( + color: const Color(0xFF1E1E1E), + padding: const EdgeInsets.symmetric(horizontal: 16, vertical: 12), + child: Row( + mainAxisAlignment: MainAxisAlignment.spaceAround, + children: [ + _StatItem( + icon: Icons.chat_bubble_outline, + value: '$messageCount', + label: 'Messages', + ), + _StatItem( + icon: Icons.build_outlined, + value: '$toolUseCount', + label: 'Tool Uses', + ), + _StatItem( + icon: Icons.timer_outlined, + value: duration != null ? _formatDuration(duration!) : '—', + label: 'Duration', + ), + ], + ), + ); + } +} + +class _StatItem extends StatelessWidget { + final IconData icon; + final String value; + final String label; + + const _StatItem({ + required this.icon, + required this.value, + required this.label, + }); + + @override + Widget build(BuildContext context) { + return Column( + children: [ + Icon(icon, size: 18, color: const Color(0xFF9E9E9E)), + const SizedBox(height: 4), + Text( + value, + style: const TextStyle( + fontSize: 16, + fontWeight: FontWeight.w600, + color: Color(0xFFD4D4D4), + ), + ), + Text( + label, + style: const TextStyle( + fontSize: 10, + color: Color(0xFF9E9E9E), + ), + ), + ], + ); + } +} diff --git a/apps/mobile/lib/features/session/presentation/widgets/session_card.dart b/apps/mobile/lib/features/session/presentation/widgets/session_card.dart new file mode 100644 index 0000000..38e9e9b --- /dev/null +++ b/apps/mobile/lib/features/session/presentation/widgets/session_card.dart @@ -0,0 +1,136 @@ +import 'package:flutter/material.dart'; + +import '../../../../core/models/session_models.dart'; +import '../../../../shared/utils/date_formatter.dart'; + +/// A list card summarising a [ChatSession]. +class SessionCard extends StatelessWidget { + final ChatSession session; + final VoidCallback onTap; + + const SessionCard({ + super.key, + required this.session, + required this.onTap, + }); + + Widget _agentChip(String agentType) { + return Container( + padding: const EdgeInsets.symmetric(horizontal: 8, vertical: 3), + decoration: BoxDecoration( + color: const Color(0xFF252526), + borderRadius: BorderRadius.circular(4), + border: Border.all(color: const Color(0xFF3E3E3E)), + ), + child: Text( + agentType, + style: const TextStyle( + fontSize: 11, + color: Color(0xFF9E9E9E), + ), + ), + ); + } + + Widget _branchChip(String branch) { + return Container( + padding: const EdgeInsets.symmetric(horizontal: 6, vertical: 2), + decoration: BoxDecoration( + color: const Color(0xFF1E1E1E), + borderRadius: BorderRadius.circular(4), + border: Border.all(color: const Color(0xFF569CD6).withOpacity(0.4)), + ), + child: Row( + mainAxisSize: MainAxisSize.min, + children: [ + const Icon(Icons.alt_route, size: 10, color: Color(0xFF569CD6)), + const SizedBox(width: 3), + Text( + branch, + style: const TextStyle( + fontSize: 10, + color: Color(0xFF569CD6), + ), + ), + ], + ), + ); + } + + Color _statusColor(SessionStatus status) { + return switch (status) { + SessionStatus.active => const Color(0xFF4CAF50), + SessionStatus.paused => const Color(0xFFFF9800), + SessionStatus.closed => const Color(0xFF9E9E9E), + }; + } + + @override + Widget build(BuildContext context) { + final title = session.title.isEmpty ? 'Session' : session.title; + final lastActivity = + session.lastMessageAt ?? session.updatedAt ?? session.createdAt; + + return Card( + margin: const EdgeInsets.symmetric(horizontal: 12, vertical: 4), + child: InkWell( + onTap: onTap, + borderRadius: BorderRadius.circular(8), + child: Padding( + padding: const EdgeInsets.symmetric(horizontal: 12, vertical: 10), + child: Row( + children: [ + // Leading: agent type chip + _agentChip(session.agentType), + const SizedBox(width: 12), + // Content + Expanded( + child: Column( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + Text( + title, + style: const TextStyle( + fontSize: 14, + fontWeight: FontWeight.w500, + color: Color(0xFFD4D4D4), + ), + maxLines: 1, + overflow: TextOverflow.ellipsis, + ), + const SizedBox(height: 4), + Row( + children: [ + Text( + DateFormatter.formatRelative(lastActivity), + style: const TextStyle( + fontSize: 11, + color: Color(0xFF9E9E9E), + ), + ), + if (session.branch != null) ...[ + const SizedBox(width: 8), + _branchChip(session.branch!), + ], + ], + ), + ], + ), + ), + const SizedBox(width: 8), + // Trailing: status dot + Container( + width: 8, + height: 8, + decoration: BoxDecoration( + color: _statusColor(session.status), + shape: BoxShape.circle, + ), + ), + ], + ), + ), + ), + ); + } +} diff --git a/apps/mobile/lib/features/session/presentation/widgets/session_timeline.dart b/apps/mobile/lib/features/session/presentation/widgets/session_timeline.dart new file mode 100644 index 0000000..da9e50f --- /dev/null +++ b/apps/mobile/lib/features/session/presentation/widgets/session_timeline.dart @@ -0,0 +1,35 @@ +import 'package:flutter/material.dart'; + +import '../../../../core/models/session_models.dart'; +import 'timeline_tile.dart'; + +/// Renders the full list of [SessionEvent]s as a vertical timeline. +class SessionTimeline extends StatelessWidget { + final List events; + + const SessionTimeline({super.key, required this.events}); + + @override + Widget build(BuildContext context) { + if (events.isEmpty) { + return const Center( + child: Text( + 'No events yet', + style: TextStyle(color: Color(0xFF9E9E9E)), + ), + ); + } + + return ListView.builder( + padding: const EdgeInsets.symmetric(vertical: 8), + itemCount: events.length, + itemBuilder: (context, index) { + return TimelineTile( + event: events[index], + isFirst: index == 0, + isLast: index == events.length - 1, + ); + }, + ); + } +} diff --git a/apps/mobile/lib/features/session/presentation/widgets/timeline_tile.dart b/apps/mobile/lib/features/session/presentation/widgets/timeline_tile.dart new file mode 100644 index 0000000..d9bf94e --- /dev/null +++ b/apps/mobile/lib/features/session/presentation/widgets/timeline_tile.dart @@ -0,0 +1,142 @@ +import 'package:flutter/material.dart'; + +import '../../../../core/models/session_models.dart'; +import '../../../../shared/utils/date_formatter.dart'; + +/// A single row in the session timeline. +/// +/// Renders a vertical connector + dot on the left and an [_EventCard] on the +/// right. +class TimelineTile extends StatelessWidget { + final SessionEvent event; + final bool isFirst; + final bool isLast; + + const TimelineTile({ + super.key, + required this.event, + required this.isFirst, + required this.isLast, + }); + + Color _dotColor(SessionEventType type) { + return switch (type) { + SessionEventType.userMessage => const Color(0xFF569CD6), + SessionEventType.agentMessage => const Color(0xFF569CD6), + SessionEventType.toolUse => const Color(0xFFFF9800), + SessionEventType.toolResult => const Color(0xFF4EC9B0), + SessionEventType.sessionStart => const Color(0xFF4CAF50), + SessionEventType.sessionEnd => const Color(0xFF9E9E9E), + SessionEventType.hookEvent => const Color(0xFFCE9178), + }; + } + + @override + Widget build(BuildContext context) { + final dotColor = _dotColor(event.eventType); + + return Padding( + padding: const EdgeInsets.symmetric(horizontal: 16, vertical: 0), + child: Row( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + // Left column: connector line + dot + SizedBox( + width: 24, + child: Column( + children: [ + // Top connector + Container( + width: 2, + height: isFirst ? 8 : 20, + color: isFirst + ? Colors.transparent + : const Color(0xFF3E3E3E), + ), + // Dot + Container( + width: 10, + height: 10, + decoration: BoxDecoration( + color: dotColor, + shape: BoxShape.circle, + ), + ), + // Bottom connector + Container( + width: 2, + height: isLast ? 8 : 30, + color: isLast + ? Colors.transparent + : const Color(0xFF3E3E3E), + ), + ], + ), + ), + const SizedBox(width: 12), + // Right: event card + Expanded( + child: Padding( + padding: const EdgeInsets.only(bottom: 4), + child: _EventCard(event: event), + ), + ), + ], + ), + ); + } +} + +class _EventCard extends StatelessWidget { + final SessionEvent event; + + const _EventCard({required this.event}); + + @override + Widget build(BuildContext context) { + return Card( + margin: const EdgeInsets.symmetric(vertical: 4), + child: Padding( + padding: const EdgeInsets.symmetric(horizontal: 12, vertical: 8), + child: Column( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + Row( + children: [ + Expanded( + child: Text( + event.title, + style: const TextStyle( + fontSize: 13, + fontWeight: FontWeight.w500, + color: Color(0xFFD4D4D4), + ), + ), + ), + Text( + DateFormatter.formatTime(event.timestamp), + style: const TextStyle( + fontSize: 11, + color: Color(0xFF9E9E9E), + ), + ), + ], + ), + if (event.description != null) ...[ + const SizedBox(height: 4), + Text( + event.description!, + style: const TextStyle( + fontSize: 12, + color: Color(0xFF9E9E9E), + ), + maxLines: 2, + overflow: TextOverflow.ellipsis, + ), + ], + ], + ), + ), + ); + } +} diff --git a/apps/mobile/lib/features/settings/presentation/screens/settings_screen.dart b/apps/mobile/lib/features/settings/presentation/screens/settings_screen.dart new file mode 100644 index 0000000..db82722 --- /dev/null +++ b/apps/mobile/lib/features/settings/presentation/screens/settings_screen.dart @@ -0,0 +1,201 @@ +import 'package:flutter/material.dart'; +import 'package:flutter_riverpod/flutter_riverpod.dart'; + +import '../../../../core/auth/auth_provider.dart'; +import '../../../../core/providers/theme_provider.dart'; +import '../../../../core/providers/websocket_provider.dart'; +import '../../../../core/storage/preferences.dart'; +import '../widgets/setting_tile.dart'; + +// --------------------------------------------------------------------------- +// Providers +// --------------------------------------------------------------------------- + +final _preferencesProvider = Provider((ref) { + throw UnimplementedError('Override in ProviderScope overrides'); +}); + +final _themeModeProvider = StateProvider((ref) => ThemeMode.system); + +final _notificationsEnabledProvider = StateProvider((ref) => true); + +// --------------------------------------------------------------------------- +// Settings screen +// --------------------------------------------------------------------------- + +/// Main settings screen grouped into Appearance, Notifications, Bridge, +/// Account, and About sections. +class SettingsScreen extends ConsumerWidget { + const SettingsScreen({super.key}); + + @override + Widget build(BuildContext context, WidgetRef ref) { + final themeMode = ref.watch(_themeModeProvider); + final notificationsEnabled = ref.watch(_notificationsEnabledProvider); + final highContrast = ref.watch(highContrastProvider); + final authState = ref.watch(authStateProvider); + + return Scaffold( + appBar: AppBar(title: const Text('Settings')), + body: ListView( + children: [ + _SectionHeader(label: 'APPEARANCE'), + Padding( + padding: const EdgeInsets.symmetric(horizontal: 16, vertical: 8), + child: SegmentedButton( + segments: const [ + ButtonSegment(value: ThemeMode.dark, label: Text('Dark')), + ButtonSegment(value: ThemeMode.light, label: Text('Light')), + ButtonSegment(value: ThemeMode.system, label: Text('System')), + ], + selected: {themeMode}, + onSelectionChanged: (selection) { + ref.read(_themeModeProvider.notifier).state = + selection.first; + }, + ), + ), + SwitchListTile( + contentPadding: const EdgeInsets.symmetric(horizontal: 16), + title: const Text('High contrast'), + subtitle: const Text('Increases contrast for better visibility'), + value: highContrast, + onChanged: (v) { + ref.read(highContrastProvider.notifier).setHighContrast(v); + }, + ), + const Divider(height: 1), + + _SectionHeader(label: 'NOTIFICATIONS'), + SwitchListTile( + contentPadding: const EdgeInsets.symmetric(horizontal: 16), + title: const Text('Enable notifications'), + value: notificationsEnabled, + onChanged: (v) { + ref.read(_notificationsEnabledProvider.notifier).state = v; + }, + ), + const Divider(height: 1), + + _SectionHeader(label: 'BRIDGE'), + SettingTile( + leading: const Icon(Icons.link, size: 20), + title: const Text('Bridge URL'), + subtitle: const Text( + 'Not connected', + style: TextStyle(color: Color(0xFF9E9E9E), fontSize: 12), + ), + ), + SettingTile( + leading: const Icon(Icons.link_off, size: 20, + color: Color(0xFFF44747)), + title: const Text( + 'Disconnect', + style: TextStyle(color: Color(0xFFF44747)), + ), + showDivider: false, + onTap: () { + final service = ref.read(webSocketServiceProvider); + service.disconnect(); + ScaffoldMessenger.of(context).showSnackBar( + const SnackBar(content: Text('Disconnected from bridge')), + ); + }, + ), + const Divider(height: 1), + + _SectionHeader(label: 'ACCOUNT'), + SettingTile( + leading: authState.avatarUrl != null + ? CircleAvatar( + backgroundImage: + NetworkImage(authState.avatarUrl!), + radius: 16, + ) + : const CircleAvatar( + radius: 16, + child: Icon(Icons.person, size: 18), + ), + title: Text(authState.username ?? 'Unknown user'), + subtitle: const Text( + 'GitHub', + style: TextStyle(fontSize: 11, color: Color(0xFF9E9E9E)), + ), + ), + SettingTile( + leading: const Icon(Icons.logout, size: 20, + color: Color(0xFFF44747)), + title: const Text( + 'Sign Out', + style: TextStyle(color: Color(0xFFF44747)), + ), + showDivider: false, + onTap: () { + ref.read(authStateProvider.notifier).signOut(); + }, + ), + const Divider(height: 1), + + _SectionHeader(label: 'ABOUT'), + const SettingTile( + leading: Icon(Icons.info_outline, size: 20), + title: Text('Version'), + trailing: Text( + '0.1.0', + style: TextStyle( + fontSize: 13, + color: Color(0xFF9E9E9E), + fontFamily: 'JetBrainsMono', + ), + ), + ), + SettingTile( + leading: const Icon(Icons.description_outlined, size: 20), + title: const Text('Licenses'), + onTap: () => showLicensePage( + context: context, + applicationName: 'ReCursor', + applicationVersion: '0.1.0', + ), + ), + SettingTile( + leading: const Icon(Icons.open_in_new, size: 20), + title: const Text('GitHub'), + showDivider: false, + onTap: () { + // Link would be opened via url_launcher in a real implementation. + ScaffoldMessenger.of(context).showSnackBar( + const SnackBar( + content: Text('https://github.com/RecursiveDev/ReCursor'), + ), + ); + }, + ), + const SizedBox(height: 24), + ], + ), + ); + } +} + +class _SectionHeader extends StatelessWidget { + final String label; + + const _SectionHeader({required this.label}); + + @override + Widget build(BuildContext context) { + return Padding( + padding: const EdgeInsets.fromLTRB(16, 20, 16, 6), + child: Text( + label, + style: const TextStyle( + fontSize: 11, + fontWeight: FontWeight.w600, + letterSpacing: 1.0, + color: Color(0xFF9E9E9E), + ), + ), + ); + } +} diff --git a/apps/mobile/lib/features/settings/presentation/widgets/setting_tile.dart b/apps/mobile/lib/features/settings/presentation/widgets/setting_tile.dart new file mode 100644 index 0000000..0c73d95 --- /dev/null +++ b/apps/mobile/lib/features/settings/presentation/widgets/setting_tile.dart @@ -0,0 +1,42 @@ +import 'package:flutter/material.dart'; + +/// A thin wrapper around [ListTile] with consistent padding and an optional +/// bottom divider for use in settings screens. +class SettingTile extends StatelessWidget { + final Widget? leading; + final Widget title; + final Widget? subtitle; + final Widget? trailing; + final VoidCallback? onTap; + final bool showDivider; + + const SettingTile({ + super.key, + this.leading, + required this.title, + this.subtitle, + this.trailing, + this.onTap, + this.showDivider = true, + }); + + @override + Widget build(BuildContext context) { + return Column( + mainAxisSize: MainAxisSize.min, + children: [ + ListTile( + contentPadding: + const EdgeInsets.symmetric(horizontal: 16, vertical: 2), + leading: leading, + title: title, + subtitle: subtitle, + trailing: trailing, + onTap: onTap, + ), + if (showDivider) + const Divider(height: 1, indent: 16, endIndent: 16), + ], + ); + } +} diff --git a/apps/mobile/lib/features/terminal/domain/providers/terminal_provider.dart b/apps/mobile/lib/features/terminal/domain/providers/terminal_provider.dart new file mode 100644 index 0000000..296f6ac --- /dev/null +++ b/apps/mobile/lib/features/terminal/domain/providers/terminal_provider.dart @@ -0,0 +1,91 @@ +import 'dart:async'; + +import 'package:flutter_riverpod/flutter_riverpod.dart'; + +import '../../../../core/network/websocket_messages.dart'; +import '../../../../core/providers/websocket_provider.dart'; + +// --------------------------------------------------------------------------- +// Terminal output per session +// --------------------------------------------------------------------------- + +class TerminalNotifier extends StateNotifier> { + TerminalNotifier(this._ref, this._sessionId) : super([]) { + _listen(); + } + + final Ref _ref; + final String _sessionId; + StreamSubscription? _sub; + + void _listen() { + final service = _ref.read(webSocketServiceProvider); + _sub = service.messages.listen(_handleMessage); + } + + void _handleMessage(BridgeMessage msg) { + if (msg.type == BridgeMessageType.claudeEvent) { + final msgType = msg.payload['type'] as String?; + final sessionId = msg.payload['session_id'] as String?; + + if (msgType == 'terminal_output' && sessionId == _sessionId) { + final line = msg.payload['data'] as String? ?? ''; + state = [...state, line]; + } + } + } + + /// Sends a `terminal_create` WS message. + void createSession(String sessionId, String workingDir) { + final service = _ref.read(webSocketServiceProvider); + service.send(BridgeMessage( + type: BridgeMessageType.claudeEvent, + timestamp: DateTime.now().toUtc(), + payload: { + 'type': 'terminal_create', + 'session_id': sessionId, + 'working_directory': workingDir, + }, + )); + } + + /// Sends a `terminal_input` WS message and echoes the command locally. + void sendInput(String sessionId, String command) { + final service = _ref.read(webSocketServiceProvider); + service.send(BridgeMessage( + type: BridgeMessageType.claudeEvent, + timestamp: DateTime.now().toUtc(), + payload: { + 'type': 'terminal_input', + 'session_id': sessionId, + 'data': '$command\n', + }, + )); + // Echo locally so the user sees their own input immediately. + state = [...state, '\$ $command']; + } + + /// Sends a `terminal_close` WS message. + void closeSession(String sessionId) { + final service = _ref.read(webSocketServiceProvider); + service.send(BridgeMessage( + type: BridgeMessageType.claudeEvent, + timestamp: DateTime.now().toUtc(), + payload: { + 'type': 'terminal_close', + 'session_id': sessionId, + }, + )); + } + + @override + void dispose() { + _sub?.cancel(); + super.dispose(); + } +} + +final terminalOutputProvider = + StateNotifierProvider.family, String>( + (ref, sessionId) => TerminalNotifier(ref, sessionId), +); diff --git a/apps/mobile/lib/features/terminal/presentation/screens/terminal_screen.dart b/apps/mobile/lib/features/terminal/presentation/screens/terminal_screen.dart new file mode 100644 index 0000000..9681053 --- /dev/null +++ b/apps/mobile/lib/features/terminal/presentation/screens/terminal_screen.dart @@ -0,0 +1,329 @@ +import 'package:flutter/material.dart'; +import 'package:flutter/services.dart'; +import 'package:flutter_riverpod/flutter_riverpod.dart'; + +import '../../domain/providers/terminal_provider.dart'; +import '../widgets/terminal_output.dart'; + +/// Terminal emulator screen backed by a WebSocket bridge session. +class TerminalScreen extends ConsumerStatefulWidget { + final String sessionId; + final String workingDirectory; + + const TerminalScreen({ + super.key, + required this.sessionId, + this.workingDirectory = '~', + }); + + @override + ConsumerState createState() => _TerminalScreenState(); +} + +class _TerminalScreenState extends ConsumerState { + final _inputController = TextEditingController(); + final _scrollController = ScrollController(); + final _historyScrollController = ScrollController(); + final _focusNode = FocusNode(); + + final List _commandHistory = []; + int _historyIndex = -1; + static const int _maxHistory = 50; + + @override + void initState() { + super.initState(); + WidgetsBinding.instance.addPostFrameCallback((_) { + ref + .read(terminalOutputProvider(widget.sessionId).notifier) + .createSession(widget.sessionId, widget.workingDirectory); + }); + } + + @override + void dispose() { + _inputController.dispose(); + _scrollController.dispose(); + _historyScrollController.dispose(); + _focusNode.dispose(); + super.dispose(); + } + + void _sendCommand() { + final command = _inputController.text.trim(); + if (command.isEmpty) return; + _inputController.clear(); + _historyIndex = -1; + + // Add to history (avoid consecutive duplicates) + if (_commandHistory.isEmpty || _commandHistory.last != command) { + setState(() { + _commandHistory.add(command); + if (_commandHistory.length > _maxHistory) { + _commandHistory.removeAt(0); + } + }); + } + + ref + .read(terminalOutputProvider(widget.sessionId).notifier) + .sendInput(widget.sessionId, command); + + WidgetsBinding.instance.addPostFrameCallback((_) => _scrollToBottom()); + } + + void _scrollToBottom() { + if (_scrollController.hasClients) { + _scrollController.animateTo( + _scrollController.position.maxScrollExtent, + duration: const Duration(milliseconds: 150), + curve: Curves.easeOut, + ); + } + } + + void _recallHistory(int direction) { + // direction: -1 = up (older), +1 = down (newer) + if (_commandHistory.isEmpty) return; + setState(() { + _historyIndex = (_historyIndex - direction).clamp( + -1, + _commandHistory.length - 1, + ); + if (_historyIndex == -1) { + _inputController.clear(); + } else { + final idx = _commandHistory.length - 1 - _historyIndex; + _inputController.text = _commandHistory[idx]; + _inputController.selection = TextSelection.fromPosition( + TextPosition(offset: _inputController.text.length), + ); + } + }); + } + + KeyEventResult _handleKeyEvent(FocusNode node, KeyEvent event) { + if (event is KeyDownEvent) { + if (event.logicalKey == LogicalKeyboardKey.arrowUp) { + _recallHistory(-1); + return KeyEventResult.handled; + } else if (event.logicalKey == LogicalKeyboardKey.arrowDown) { + _recallHistory(1); + return KeyEventResult.handled; + } + } + return KeyEventResult.ignored; + } + + Widget _buildTerminalOutput() { + final lines = ref.watch(terminalOutputProvider(widget.sessionId)); + return TerminalOutput(lines: lines); + } + + Widget _buildInputBar() { + return _InputBar( + controller: _inputController, + focusNode: _focusNode, + onSend: _sendCommand, + onKeyEvent: _handleKeyEvent, + ); + } + + Widget _buildHistoryList() { + return ListView.builder( + controller: _historyScrollController, + padding: const EdgeInsets.symmetric(vertical: 4), + itemCount: _commandHistory.length, + itemBuilder: (context, index) { + // Show most recent at top + final cmd = _commandHistory[_commandHistory.length - 1 - index]; + return InkWell( + onTap: () { + _inputController.text = cmd; + _inputController.selection = TextSelection.fromPosition( + TextPosition(offset: cmd.length), + ); + _focusNode.requestFocus(); + }, + child: Padding( + padding: const EdgeInsets.symmetric(horizontal: 12, vertical: 5), + child: Text( + cmd, + style: const TextStyle( + fontFamily: 'JetBrainsMono', + fontSize: 12, + color: Color(0xFFD4D4D4), + ), + overflow: TextOverflow.ellipsis, + ), + ), + ); + }, + ); + } + + @override + Widget build(BuildContext context) { + // Auto-scroll when new lines arrive. + ref.listen(terminalOutputProvider(widget.sessionId), (_, __) { + WidgetsBinding.instance + .addPostFrameCallback((_) => _scrollToBottom()); + }); + + return Scaffold( + backgroundColor: const Color(0xFF0D1117), + appBar: AppBar( + backgroundColor: const Color(0xFF161B22), + title: Column( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + const Text('Terminal', + style: TextStyle(fontSize: 15, color: Color(0xFFD4D4D4))), + Text( + widget.workingDirectory, + style: const TextStyle( + fontSize: 11, + color: Color(0xFF9E9E9E), + fontFamily: 'JetBrainsMono', + ), + ), + ], + ), + ), + body: LayoutBuilder( + builder: (context, constraints) { + final isLandscape = constraints.maxWidth > 600; + + if (isLandscape) { + return Row( + children: [ + // Left 60%: terminal output + Flexible( + flex: 60, + child: Column( + children: [ + Expanded(child: _buildTerminalOutput()), + ], + ), + ), + const VerticalDivider( + width: 1, + color: Color(0xFF30363D), + ), + // Right 40%: command history + input at bottom + Flexible( + flex: 40, + child: Container( + color: const Color(0xFF0D1117), + child: Column( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + Container( + color: const Color(0xFF161B22), + padding: const EdgeInsets.symmetric( + horizontal: 12, vertical: 6), + width: double.infinity, + child: const Text( + 'History', + style: TextStyle( + fontSize: 11, + color: Color(0xFF9E9E9E), + fontFamily: 'JetBrainsMono', + ), + ), + ), + Expanded(child: _buildHistoryList()), + const Divider(height: 1, color: Color(0xFF30363D)), + _buildInputBar(), + ], + ), + ), + ), + ], + ); + } + + // Portrait layout + return Column( + children: [ + Expanded(child: _buildTerminalOutput()), + _buildInputBar(), + ], + ); + }, + ), + ); + } +} + +class _InputBar extends StatelessWidget { + final TextEditingController controller; + final FocusNode focusNode; + final VoidCallback onSend; + final KeyEventResult Function(FocusNode, KeyEvent) onKeyEvent; + + const _InputBar({ + required this.controller, + required this.focusNode, + required this.onSend, + required this.onKeyEvent, + }); + + @override + Widget build(BuildContext context) { + return Container( + color: const Color(0xFF161B22), + padding: const EdgeInsets.symmetric(horizontal: 12, vertical: 8), + child: Row( + children: [ + const Text( + '\$', + style: TextStyle( + color: Color(0xFF4EC9B0), + fontFamily: 'JetBrainsMono', + fontSize: 14, + fontWeight: FontWeight.bold, + ), + ), + const SizedBox(width: 8), + Expanded( + child: Focus( + focusNode: focusNode, + onKeyEvent: onKeyEvent, + child: TextField( + controller: controller, + style: const TextStyle( + fontFamily: 'JetBrainsMono', + fontSize: 13, + color: Color(0xFFD4D4D4), + ), + decoration: const InputDecoration( + isDense: true, + border: InputBorder.none, + enabledBorder: InputBorder.none, + focusedBorder: InputBorder.none, + hintText: 'Enter command…', + hintStyle: TextStyle( + fontFamily: 'JetBrainsMono', + fontSize: 13, + color: Color(0xFF555555), + ), + filled: false, + ), + onSubmitted: (_) => onSend(), + autocorrect: false, + enableSuggestions: false, + ), + ), + ), + IconButton( + onPressed: onSend, + icon: const Icon(Icons.send, size: 18), + color: const Color(0xFF569CD6), + padding: EdgeInsets.zero, + ), + ], + ), + ); + } +} diff --git a/apps/mobile/lib/features/terminal/presentation/widgets/ansi_renderer.dart b/apps/mobile/lib/features/terminal/presentation/widgets/ansi_renderer.dart new file mode 100644 index 0000000..5feb294 --- /dev/null +++ b/apps/mobile/lib/features/terminal/presentation/widgets/ansi_renderer.dart @@ -0,0 +1,32 @@ +import 'package:flutter/material.dart'; + +import '../../../../shared/utils/ansi_parser.dart'; + +/// Converts a terminal output line (potentially containing ANSI escape codes) +/// into a [InlineSpan] suitable for a [RichText] widget. +class AnsiRenderer { + AnsiRenderer._(); + + static InlineSpan render(String line) { + final spans = AnsiParser.parse(line); + + if (spans.isEmpty) { + return const TextSpan(text: ''); + } + + final children = spans.map((span) { + return TextSpan( + text: span.text, + style: TextStyle( + color: span.color ?? const Color(0xFFD4D4D4), + fontWeight: span.bold ? FontWeight.bold : FontWeight.normal, + fontStyle: span.italic ? FontStyle.italic : FontStyle.normal, + fontFamily: 'JetBrainsMono', + fontSize: 13, + ), + ); + }).toList(); + + return TextSpan(children: children); + } +} diff --git a/apps/mobile/lib/features/terminal/presentation/widgets/terminal_output.dart b/apps/mobile/lib/features/terminal/presentation/widgets/terminal_output.dart new file mode 100644 index 0000000..84344ed --- /dev/null +++ b/apps/mobile/lib/features/terminal/presentation/widgets/terminal_output.dart @@ -0,0 +1,26 @@ +import 'package:flutter/material.dart'; + +import 'ansi_renderer.dart'; + +/// Renders a list of terminal output lines with ANSI colour support. +class TerminalOutput extends StatelessWidget { + final List lines; + + const TerminalOutput({super.key, required this.lines}); + + @override + Widget build(BuildContext context) { + return Container( + color: const Color(0xFF0D1117), + child: ListView.builder( + padding: const EdgeInsets.symmetric(horizontal: 8, vertical: 4), + itemCount: lines.length, + itemBuilder: (context, index) { + return RichText( + text: AnsiRenderer.render(lines[index]), + ); + }, + ), + ); + } +} diff --git a/apps/mobile/lib/main.dart b/apps/mobile/lib/main.dart new file mode 100644 index 0000000..ea54bfe --- /dev/null +++ b/apps/mobile/lib/main.dart @@ -0,0 +1,30 @@ +import 'package:flutter/material.dart'; +import 'package:flutter_riverpod/flutter_riverpod.dart'; +import 'package:hive_flutter/hive_flutter.dart'; + +import 'app.dart'; +import 'core/monitoring/sentry_service.dart'; +import 'core/providers/theme_provider.dart'; +import 'core/storage/preferences.dart'; + +void main() async { + WidgetsFlutterBinding.ensureInitialized(); + await Hive.initFlutter(); + + final prefs = AppPreferences(); + await prefs.init(); + + FlutterError.onError = (details) { + FlutterError.presentError(details); + SentryService.captureException(details.exception, stackTrace: details.stack); + }; + + await SentryService.init(() => runApp( + ProviderScope( + overrides: [ + appPreferencesProvider.overrideWithValue(prefs), + ], + child: const ReCursorApp(), + ), + )); +} diff --git a/apps/mobile/lib/shared/constants/colors.dart b/apps/mobile/lib/shared/constants/colors.dart new file mode 100644 index 0000000..9b18f4c --- /dev/null +++ b/apps/mobile/lib/shared/constants/colors.dart @@ -0,0 +1,34 @@ +import 'package:flutter/material.dart'; + +import '../../core/config/theme.dart'; + +// Re-export AppColors constants +const kBackground = AppColors.background; +const kSurface = AppColors.surface; +const kSurfaceVariant = AppColors.surfaceVariant; +const kPrimary = AppColors.primary; +const kSecondary = AppColors.secondary; +const kError = AppColors.error; +const kAdded = AppColors.added; +const kRemoved = AppColors.removed; +const kAccent = AppColors.accent; +const kTextPrimary = AppColors.textPrimary; +const kTextSecondary = AppColors.textSecondary; +const kBorder = AppColors.border; + +// Diff line background colors +const kDiffAdded = Color(0x334EC9B0); +const kDiffRemoved = Color(0x33F44747); +const kDiffContext = Color(0x00000000); // transparent + +// Risk level colors +const kRiskLow = Color(0xFF4CAF50); +const kRiskMedium = Color(0xFFFF9800); +const kRiskHigh = Color(0xFFF44747); +const kRiskCritical = Color(0xFF8B0000); + +// Tool status colors +const kToolPending = Color(0xFF569CD6); +const kToolRunning = Color(0xFFFF9800); +const kToolCompleted = Color(0xFF4EC9B0); +const kToolError = Color(0xFFF44747); diff --git a/apps/mobile/lib/shared/constants/dimens.dart b/apps/mobile/lib/shared/constants/dimens.dart new file mode 100644 index 0000000..20a53de --- /dev/null +++ b/apps/mobile/lib/shared/constants/dimens.dart @@ -0,0 +1,22 @@ +class Dimens { + static const double paddingXS = 4; + static const double paddingS = 8; + static const double paddingM = 16; + static const double paddingL = 24; + static const double paddingXL = 32; + + static const double radiusS = 4; + static const double radiusM = 8; + static const double radiusL = 16; + + static const double iconS = 16; + static const double iconM = 24; + static const double iconL = 32; + + static const double cardElevation = 2; + static const double appBarHeight = 56; + static const double bottomNavHeight = 60; + static const double inputHeight = 48; + + static const double tabletBreakpoint = 600; +} diff --git a/apps/mobile/lib/shared/constants/typography.dart b/apps/mobile/lib/shared/constants/typography.dart new file mode 100644 index 0000000..d99e3f6 --- /dev/null +++ b/apps/mobile/lib/shared/constants/typography.dart @@ -0,0 +1,29 @@ +import 'package:flutter/material.dart'; + +class AppTypography { + static const String monoFont = 'JetBrainsMono'; + + static const TextStyle code = TextStyle( + fontFamily: monoFont, + fontSize: 13, + color: Color(0xFFD4D4D4), + ); + + static const TextStyle codeSmall = TextStyle( + fontFamily: monoFont, + fontSize: 11, + color: Color(0xFF9E9E9E), + ); + + static const TextStyle label = TextStyle( + fontSize: 12, + fontWeight: FontWeight.w500, + letterSpacing: 0.5, + ); + + static const TextStyle sectionHeader = TextStyle( + fontSize: 11, + fontWeight: FontWeight.w600, + letterSpacing: 1.0, + ); +} diff --git a/apps/mobile/lib/shared/utils/ansi_parser.dart b/apps/mobile/lib/shared/utils/ansi_parser.dart new file mode 100644 index 0000000..47bc890 --- /dev/null +++ b/apps/mobile/lib/shared/utils/ansi_parser.dart @@ -0,0 +1,112 @@ +import 'package:flutter/material.dart'; + +class AnsiSpan { + final String text; + final Color? color; + final bool bold; + final bool italic; + + const AnsiSpan( + this.text, { + this.color, + this.bold = false, + this.italic = false, + }); +} + +/// Parses ANSI escape codes from terminal output. +class AnsiParser { + static final _ansiEscapePattern = RegExp(r'\x1B\[[0-9;]*m'); + + // Standard 8/16 ANSI foreground color table (codes 30–37, bright 90–97) + static const _fgColors = { + 30: Color(0xFF000000), // black + 31: Color(0xFFCD3131), // red + 32: Color(0xFF0DBC79), // green + 33: Color(0xFFE5E510), // yellow + 34: Color(0xFF2472C8), // blue + 35: Color(0xFFBC3FBC), // magenta + 36: Color(0xFF11A8CD), // cyan + 37: Color(0xFFE5E5E5), // white + 90: Color(0xFF666666), // bright black (gray) + 91: Color(0xFFF14C4C), // bright red + 92: Color(0xFF23D18B), // bright green + 93: Color(0xFFF5F543), // bright yellow + 94: Color(0xFF3B8EEA), // bright blue + 95: Color(0xFFD670D6), // bright magenta + 96: Color(0xFF29B8DB), // bright cyan + 97: Color(0xFFFFFFFF), // bright white + }; + + /// Remove all ANSI escape sequences from [text]. + static String stripAnsi(String text) { + return text.replaceAll(_ansiEscapePattern, ''); + } + + /// Parse [text] containing ANSI escape sequences into a list of [AnsiSpan]s. + static List parse(String text) { + final spans = []; + + Color? currentColor; + bool bold = false; + bool italic = false; + + int cursor = 0; + + final matches = _ansiEscapePattern.allMatches(text).toList(); + + for (final match in matches) { + // Append plain text before this escape sequence + if (match.start > cursor) { + final plain = text.substring(cursor, match.start); + if (plain.isNotEmpty) { + spans.add(AnsiSpan(plain, color: currentColor, bold: bold, italic: italic)); + } + } + + // Parse the escape sequence codes + final sequence = match.group(0)!; + final inner = sequence.substring(2, sequence.length - 1); // strip ESC[ and m + final codes = inner.isEmpty + ? [0] + : inner.split(';').map((s) => int.tryParse(s) ?? 0).toList(); + + for (final code in codes) { + if (code == 0) { + // Reset + currentColor = null; + bold = false; + italic = false; + } else if (code == 1) { + bold = true; + } else if (code == 3) { + italic = true; + } else if (code == 22) { + bold = false; + } else if (code == 23) { + italic = false; + } else if (_fgColors.containsKey(code)) { + currentColor = _fgColors[code]; + } + // Background colors (40–47) are parsed but ignored for spans + } + + cursor = match.end; + } + + // Remaining text after the last escape sequence + if (cursor < text.length) { + final remaining = text.substring(cursor); + if (remaining.isNotEmpty) { + spans.add(AnsiSpan(remaining, color: currentColor, bold: bold, italic: italic)); + } + } + + // If no escape sequences were found, return the whole string as one span + if (spans.isEmpty && text.isNotEmpty) { + spans.add(AnsiSpan(text)); + } + + return spans; + } +} diff --git a/apps/mobile/lib/shared/utils/date_formatter.dart b/apps/mobile/lib/shared/utils/date_formatter.dart new file mode 100644 index 0000000..2cca00b --- /dev/null +++ b/apps/mobile/lib/shared/utils/date_formatter.dart @@ -0,0 +1,55 @@ +class DateFormatter { + static const _months = [ + 'Jan', 'Feb', 'Mar', 'Apr', 'May', 'Jun', + 'Jul', 'Aug', 'Sep', 'Oct', 'Nov', 'Dec', + ]; + + /// Returns a human-readable relative time string. + /// Examples: "just now", "2m ago", "1h ago", "yesterday", "Mar 15" + static String formatRelative(DateTime dt) { + final now = DateTime.now(); + final diff = now.difference(dt); + + if (diff.inSeconds < 60) return 'just now'; + if (diff.inMinutes < 60) return '${diff.inMinutes}m ago'; + if (diff.inHours < 24) return '${diff.inHours}h ago'; + + final today = DateTime(now.year, now.month, now.day); + final dtDay = DateTime(dt.year, dt.month, dt.day); + final dayDiff = today.difference(dtDay).inDays; + + if (dayDiff == 1) return 'yesterday'; + + return '${_months[dt.month - 1]} ${dt.day}'; + } + + /// Returns a full date-time string. + /// Example: "Mar 15, 2026 10:32 AM" + static String formatFull(DateTime dt) { + final month = _months[dt.month - 1]; + final time = formatTime(dt); + return '$month ${dt.day}, ${dt.year} $time'; + } + + /// Returns a time-only string. + /// Example: "10:32 AM" + static String formatTime(DateTime dt) { + final hour = dt.hour % 12 == 0 ? 12 : dt.hour % 12; + final minute = dt.minute.toString().padLeft(2, '0'); + final period = dt.hour < 12 ? 'AM' : 'PM'; + return '$hour:$minute $period'; + } + + /// Returns a human-readable duration string. + /// Examples: "1h 23m", "45s" + static String formatDuration(Duration d) { + if (d.inHours > 0) { + final minutes = d.inMinutes.remainder(60); + return '${d.inHours}h ${minutes}m'; + } + if (d.inMinutes > 0) { + return '${d.inMinutes}m'; + } + return '${d.inSeconds}s'; + } +} diff --git a/apps/mobile/lib/shared/utils/diff_parser.dart b/apps/mobile/lib/shared/utils/diff_parser.dart new file mode 100644 index 0000000..7293732 --- /dev/null +++ b/apps/mobile/lib/shared/utils/diff_parser.dart @@ -0,0 +1,158 @@ +import '../../core/models/git_models.dart'; + +/// Parses unified diff strings into [DiffFile] objects. +class DiffParser { + static final _fileHeaderOld = RegExp(r'^--- a/(.+)$'); + static final _fileHeaderNew = RegExp(r'^\+\+\+ b/(.+)$'); + static final _hunkHeader = RegExp( + r'^@@ -(\d+)(?:,(\d+))? \+(\d+)(?:,(\d+))? @@(.*)$', + ); + + /// Parse a unified diff string into a list of [DiffFile] objects. + static List parse(String rawDiff) { + final files = []; + final lines = rawDiff.split('\n'); + + String? oldPath; + String? newPath; + final hunks = []; + + List? currentHunkLines; + DiffHunk? currentHunk; + int oldLineNum = 0; + int newLineNum = 0; + + void flushHunk() { + if (currentHunk != null && currentHunkLines != null) { + hunks.add(DiffHunk( + header: currentHunk!.header, + oldStart: currentHunk!.oldStart, + oldLines: currentHunk!.oldLines, + newStart: currentHunk!.newStart, + newLines: currentHunk!.newLines, + lines: List.unmodifiable(currentHunkLines!), + )); + currentHunk = null; + currentHunkLines = null; + } + } + + void flushFile() { + if (oldPath != null && newPath != null) { + flushHunk(); + + int additions = 0; + int deletions = 0; + for (final hunk in hunks) { + for (final line in hunk.lines) { + if (line.type == DiffLineType.added) additions++; + if (line.type == DiffLineType.removed) deletions++; + } + } + + final path = newPath ?? oldPath ?? ''; + files.add(DiffFile( + path: path, + oldPath: oldPath!, + newPath: newPath!, + status: _inferStatus(oldPath!, newPath!), + additions: additions, + deletions: deletions, + hunks: List.unmodifiable(hunks), + )); + + oldPath = null; + newPath = null; + hunks.clear(); + } + } + + for (final line in lines) { + // New file header signals start of a new file diff + if (line.startsWith('--- ')) { + final match = _fileHeaderOld.firstMatch(line); + if (match != null) { + flushFile(); + oldPath = match.group(1); + continue; + } + // Handle /dev/null for new files + if (line == '--- /dev/null') { + flushFile(); + oldPath = '/dev/null'; + continue; + } + } + + if (line.startsWith('+++ ')) { + final match = _fileHeaderNew.firstMatch(line); + if (match != null) { + newPath = match.group(1); + continue; + } + if (line == '+++ /dev/null') { + newPath = '/dev/null'; + continue; + } + } + + // Hunk header + final hunkMatch = _hunkHeader.firstMatch(line); + if (hunkMatch != null) { + flushHunk(); + final oldStart = int.parse(hunkMatch.group(1)!); + final oldCount = int.tryParse(hunkMatch.group(2) ?? '1') ?? 1; + final newStart = int.parse(hunkMatch.group(3)!); + final newCount = int.tryParse(hunkMatch.group(4) ?? '1') ?? 1; + final header = line; + + currentHunk = DiffHunk( + header: header, + oldStart: oldStart, + oldLines: oldCount, + newStart: newStart, + newLines: newCount, + lines: const [], + ); + currentHunkLines = []; + oldLineNum = oldStart; + newLineNum = newStart; + continue; + } + + // Diff content lines + if (currentHunkLines != null) { + if (line.startsWith('+')) { + currentHunkLines!.add(DiffLine( + type: DiffLineType.added, + content: line.substring(1), + newLineNumber: newLineNum++, + )); + } else if (line.startsWith('-')) { + currentHunkLines!.add(DiffLine( + type: DiffLineType.removed, + content: line.substring(1), + oldLineNumber: oldLineNum++, + )); + } else if (line.startsWith(' ')) { + currentHunkLines!.add(DiffLine( + type: DiffLineType.context, + content: line.substring(1), + oldLineNumber: oldLineNum++, + newLineNumber: newLineNum++, + )); + } + } + } + + flushFile(); + return files; + } + + static FileChangeStatus _inferStatus(String oldPath, String newPath) { + if (oldPath == '/dev/null') return FileChangeStatus.added; + if (newPath == '/dev/null') return FileChangeStatus.deleted; + if (oldPath != newPath) return FileChangeStatus.renamed; + return FileChangeStatus.modified; + } +} diff --git a/apps/mobile/lib/shared/widgets/code_block.dart b/apps/mobile/lib/shared/widgets/code_block.dart new file mode 100644 index 0000000..7ce06c0 --- /dev/null +++ b/apps/mobile/lib/shared/widgets/code_block.dart @@ -0,0 +1,109 @@ +import 'package:flutter/material.dart'; +import 'package:flutter/services.dart'; + +import '../constants/colors.dart'; +import '../constants/typography.dart'; + +class CodeBlock extends StatelessWidget { + final String code; + final String? language; + final bool showCopyButton; + + const CodeBlock({ + super.key, + required this.code, + this.language, + this.showCopyButton = true, + }); + + @override + Widget build(BuildContext context) { + return Container( + width: double.infinity, + decoration: BoxDecoration( + color: kSurfaceVariant, + borderRadius: BorderRadius.circular(8), + border: Border.all(color: kBorder), + ), + child: Column( + crossAxisAlignment: CrossAxisAlignment.stretch, + children: [ + if (language != null || showCopyButton) + _buildHeader(context), + SingleChildScrollView( + scrollDirection: Axis.horizontal, + padding: const EdgeInsets.all(12), + child: Text( + code, + style: AppTypography.code, + ), + ), + ], + ), + ); + } + + Widget _buildHeader(BuildContext context) { + return Container( + padding: const EdgeInsets.symmetric(horizontal: 12, vertical: 6), + decoration: const BoxDecoration( + border: Border(bottom: BorderSide(color: kBorder)), + ), + child: Row( + mainAxisAlignment: MainAxisAlignment.spaceBetween, + children: [ + if (language != null) + Text( + language!, + style: AppTypography.codeSmall, + ) + else + const SizedBox.shrink(), + if (showCopyButton) + _CopyButton(code: code), + ], + ), + ); + } +} + +class _CopyButton extends StatefulWidget { + final String code; + const _CopyButton({required this.code}); + + @override + State<_CopyButton> createState() => _CopyButtonState(); +} + +class _CopyButtonState extends State<_CopyButton> { + bool _copied = false; + + Future _onCopy() async { + await Clipboard.setData(ClipboardData(text: widget.code)); + setState(() => _copied = true); + await Future.delayed(const Duration(seconds: 2)); + if (mounted) setState(() => _copied = false); + } + + @override + Widget build(BuildContext context) { + return GestureDetector( + onTap: _onCopy, + child: Row( + mainAxisSize: MainAxisSize.min, + children: [ + Icon( + _copied ? Icons.check : Icons.copy, + size: 14, + color: kTextSecondary, + ), + const SizedBox(width: 4), + Text( + _copied ? 'Copied' : 'Copy', + style: AppTypography.codeSmall, + ), + ], + ), + ); + } +} diff --git a/apps/mobile/lib/shared/widgets/connection_status_bar.dart b/apps/mobile/lib/shared/widgets/connection_status_bar.dart new file mode 100644 index 0000000..3c0cd85 --- /dev/null +++ b/apps/mobile/lib/shared/widgets/connection_status_bar.dart @@ -0,0 +1,45 @@ +import 'package:flutter/material.dart'; +import 'package:flutter_riverpod/flutter_riverpod.dart'; + +import '../../core/network/connection_state.dart'; +import '../../core/providers/websocket_provider.dart'; + +class ConnectionStatusBar extends ConsumerWidget { + const ConnectionStatusBar({super.key}); + + @override + Widget build(BuildContext context, WidgetRef ref) { + final statusAsync = ref.watch(connectionStatusProvider); + return statusAsync.when( + data: (status) => _buildBar(status), + loading: () => const SizedBox.shrink(), + error: (_, __) => const SizedBox.shrink(), + ); + } + + Widget _buildBar(ConnectionStatus status) { + if (status == ConnectionStatus.connected) return const SizedBox.shrink(); + + final isReconnecting = status == ConnectionStatus.reconnecting; + final color = isReconnecting + ? const Color(0xFFFF9800) + : const Color(0xFFF44747); + final message = isReconnecting ? 'Reconnecting...' : 'Offline'; + + return AnimatedContainer( + duration: const Duration(milliseconds: 300), + width: double.infinity, + color: color, + padding: const EdgeInsets.symmetric(vertical: 3), + child: Text( + message, + textAlign: TextAlign.center, + style: const TextStyle( + color: Colors.white, + fontSize: 12, + fontWeight: FontWeight.w500, + ), + ), + ); + } +} diff --git a/apps/mobile/lib/shared/widgets/empty_state.dart b/apps/mobile/lib/shared/widgets/empty_state.dart new file mode 100644 index 0000000..f61a8a7 --- /dev/null +++ b/apps/mobile/lib/shared/widgets/empty_state.dart @@ -0,0 +1,59 @@ +import 'package:flutter/material.dart'; + +class EmptyState extends StatelessWidget { + final IconData icon; + final String title; + final String? subtitle; + final String? actionLabel; + final VoidCallback? onAction; + + const EmptyState({ + super.key, + required this.icon, + required this.title, + this.subtitle, + this.actionLabel, + this.onAction, + }); + + @override + Widget build(BuildContext context) { + final theme = Theme.of(context); + return Center( + child: Padding( + padding: const EdgeInsets.all(32), + child: Column( + mainAxisSize: MainAxisSize.min, + children: [ + Icon( + icon, + size: 56, + color: theme.colorScheme.onSurface.withOpacity(0.3), + ), + const SizedBox(height: 16), + Text( + title, + style: theme.textTheme.titleMedium, + textAlign: TextAlign.center, + ), + if (subtitle != null) ...[ + const SizedBox(height: 8), + Text( + subtitle!, + style: theme.textTheme.bodySmall, + textAlign: TextAlign.center, + ), + ], + if (actionLabel != null && onAction != null) ...[ + const SizedBox(height: 20), + FilledButton( + onPressed: onAction, + child: Text(actionLabel!), + ), + ], + ], + ), + ), + ); + } +} diff --git a/apps/mobile/lib/shared/widgets/error_card.dart b/apps/mobile/lib/shared/widgets/error_card.dart new file mode 100644 index 0000000..5bc6b3c --- /dev/null +++ b/apps/mobile/lib/shared/widgets/error_card.dart @@ -0,0 +1,55 @@ +import 'package:flutter/material.dart'; + +class ErrorCard extends StatelessWidget { + final String message; + final VoidCallback? onRetry; + + const ErrorCard({ + super.key, + required this.message, + this.onRetry, + }); + + @override + Widget build(BuildContext context) { + final theme = Theme.of(context); + return Card( + child: Padding( + padding: const EdgeInsets.all(16), + child: Column( + mainAxisSize: MainAxisSize.min, + children: [ + Icon( + Icons.error_outline, + color: theme.colorScheme.error, + size: 32, + ), + const SizedBox(height: 8), + Semantics( + label: message, + child: Text( + message, + style: theme.textTheme.bodyMedium?.copyWith( + color: theme.colorScheme.error, + ), + textAlign: TextAlign.center, + ), + ), + if (onRetry != null) ...[ + const SizedBox(height: 12), + Semantics( + label: 'Retry', + button: true, + child: TextButton.icon( + onPressed: onRetry, + icon: const Icon(Icons.refresh), + label: const Text('Retry'), + ), + ), + ], + ], + ), + ), + ); + } +} diff --git a/apps/mobile/lib/shared/widgets/expandable_card.dart b/apps/mobile/lib/shared/widgets/expandable_card.dart new file mode 100644 index 0000000..7856448 --- /dev/null +++ b/apps/mobile/lib/shared/widgets/expandable_card.dart @@ -0,0 +1,96 @@ +import 'package:flutter/material.dart'; + +class ExpandableCard extends StatefulWidget { + final Widget header; + final Widget content; + final bool initiallyExpanded; + + const ExpandableCard({ + super.key, + required this.header, + required this.content, + this.initiallyExpanded = false, + }); + + @override + State createState() => _ExpandableCardState(); +} + +class _ExpandableCardState extends State + with SingleTickerProviderStateMixin { + late bool _expanded; + late AnimationController _controller; + late Animation _chevronRotation; + late Animation _expandAnimation; + + @override + void initState() { + super.initState(); + _expanded = widget.initiallyExpanded; + _controller = AnimationController( + vsync: this, + duration: const Duration(milliseconds: 200), + value: _expanded ? 1.0 : 0.0, + ); + _chevronRotation = Tween(begin: 0.0, end: 0.5).animate( + CurvedAnimation(parent: _controller, curve: Curves.easeInOut), + ); + _expandAnimation = CurvedAnimation( + parent: _controller, + curve: Curves.easeInOut, + ); + } + + @override + void dispose() { + _controller.dispose(); + super.dispose(); + } + + void _toggle() { + setState(() { + _expanded = !_expanded; + if (_expanded) { + _controller.forward(); + } else { + _controller.reverse(); + } + }); + } + + @override + Widget build(BuildContext context) { + return Card( + child: Column( + mainAxisSize: MainAxisSize.min, + children: [ + InkWell( + onTap: _toggle, + borderRadius: const BorderRadius.vertical(top: Radius.circular(12)), + child: Padding( + padding: const EdgeInsets.symmetric(horizontal: 12, vertical: 10), + child: Row( + children: [ + Expanded(child: widget.header), + RotationTransition( + turns: _chevronRotation, + child: const Icon(Icons.expand_more), + ), + ], + ), + ), + ), + SizeTransition( + sizeFactor: _expandAnimation, + child: Column( + children: [ + const Divider(height: 1), + widget.content, + ], + ), + ), + ], + ), + ); + } +} diff --git a/apps/mobile/lib/shared/widgets/loading_indicator.dart b/apps/mobile/lib/shared/widgets/loading_indicator.dart new file mode 100644 index 0000000..f2689f0 --- /dev/null +++ b/apps/mobile/lib/shared/widgets/loading_indicator.dart @@ -0,0 +1,30 @@ +import 'package:flutter/material.dart'; + +class LoadingIndicator extends StatelessWidget { + final String? message; + + const LoadingIndicator({super.key, this.message}); + + @override + Widget build(BuildContext context) { + return Center( + child: Column( + mainAxisSize: MainAxisSize.min, + children: [ + Semantics( + label: message ?? 'Loading', + child: const CircularProgressIndicator(), + ), + if (message != null) ...[ + const SizedBox(height: 12), + Text( + message!, + style: Theme.of(context).textTheme.bodyMedium, + textAlign: TextAlign.center, + ), + ], + ], + ), + ); + } +} diff --git a/apps/mobile/lib/shared/widgets/markdown_view.dart b/apps/mobile/lib/shared/widgets/markdown_view.dart new file mode 100644 index 0000000..2d1a7e6 --- /dev/null +++ b/apps/mobile/lib/shared/widgets/markdown_view.dart @@ -0,0 +1,47 @@ +import 'package:flutter/material.dart'; +import 'package:flutter_markdown/flutter_markdown.dart'; + +import '../constants/colors.dart'; +import '../constants/typography.dart'; + +class MarkdownView extends StatelessWidget { + final String data; + final bool shrinkWrap; + + const MarkdownView({ + super.key, + required this.data, + this.shrinkWrap = false, + }); + + @override + Widget build(BuildContext context) { + return Markdown( + data: data, + shrinkWrap: shrinkWrap, + styleSheet: _buildStyleSheet(context), + padding: EdgeInsets.zero, + ); + } + + MarkdownStyleSheet _buildStyleSheet(BuildContext context) { + final base = MarkdownStyleSheet.fromTheme(Theme.of(context)); + return base.copyWith( + code: AppTypography.code, + codeblockDecoration: BoxDecoration( + color: kSurfaceVariant, + borderRadius: BorderRadius.circular(8), + border: Border.all(color: kBorder), + ), + codeblockPadding: const EdgeInsets.all(12), + blockquoteDecoration: BoxDecoration( + border: Border( + left: BorderSide( + color: kPrimary.withOpacity(0.6), + width: 3, + ), + ), + ), + ); + } +} diff --git a/apps/mobile/lib/shared/widgets/risk_badge.dart b/apps/mobile/lib/shared/widgets/risk_badge.dart new file mode 100644 index 0000000..d7729ed --- /dev/null +++ b/apps/mobile/lib/shared/widgets/risk_badge.dart @@ -0,0 +1,38 @@ +import 'package:flutter/material.dart'; + +import '../constants/colors.dart'; + +class RiskBadge extends StatelessWidget { + final String riskLevel; + + const RiskBadge({super.key, required this.riskLevel}); + + Color get _color => switch (riskLevel.toLowerCase()) { + 'low' => kRiskLow, + 'medium' => kRiskMedium, + 'high' => kRiskHigh, + 'critical' => kRiskCritical, + _ => kRiskMedium, + }; + + @override + Widget build(BuildContext context) { + return Container( + padding: const EdgeInsets.symmetric(horizontal: 6, vertical: 2), + decoration: BoxDecoration( + color: _color.withOpacity(0.2), + borderRadius: BorderRadius.circular(4), + border: Border.all(color: _color.withOpacity(0.6)), + ), + child: Text( + riskLevel.toUpperCase(), + style: TextStyle( + fontSize: 10, + fontWeight: FontWeight.w700, + color: _color, + letterSpacing: 0.5, + ), + ), + ); + } +} diff --git a/apps/mobile/lib/shared/widgets/tool_icon.dart b/apps/mobile/lib/shared/widgets/tool_icon.dart new file mode 100644 index 0000000..f8b2261 --- /dev/null +++ b/apps/mobile/lib/shared/widgets/tool_icon.dart @@ -0,0 +1,35 @@ +import 'package:flutter/material.dart'; + +class ToolIcon extends StatelessWidget { + final String tool; + final double size; + final Color? color; + + const ToolIcon({ + super.key, + required this.tool, + this.size = 24, + this.color, + }); + + IconData get _icon => switch (tool.toLowerCase()) { + 'edit_file' || 'write' || 'edit' => Icons.edit, + 'read_file' || 'read' => Icons.file_open, + 'bash' || 'run_command' || 'bash_command' => Icons.terminal, + 'glob' => Icons.folder_open, + 'grep' => Icons.search, + 'list_files' || 'ls' => Icons.list, + 'git_commit' => Icons.commit, + 'git_diff' => Icons.difference, + _ => Icons.build, + }; + + @override + Widget build(BuildContext context) { + return Icon( + _icon, + size: size, + color: color ?? Theme.of(context).iconTheme.color, + ); + } +} diff --git a/apps/mobile/pubspec.lock b/apps/mobile/pubspec.lock index 359ec32..9694d86 100644 --- a/apps/mobile/pubspec.lock +++ b/apps/mobile/pubspec.lock @@ -1,6 +1,38 @@ # Generated by pub # See https://dart.dev/tools/pub/glossary#lockfile packages: + _fe_analyzer_shared: + dependency: transitive + description: + name: _fe_analyzer_shared + sha256: da0d9209ca76bde579f2da330aeb9df62b6319c834fa7baae052021b0462401f + url: "https://pub.dev" + source: hosted + version: "85.0.0" + analyzer: + dependency: transitive + description: + name: analyzer + sha256: f4ad0fea5f102201015c9aae9d93bc02f75dd9491529a8c21f88d17a8523d44c + url: "https://pub.dev" + source: hosted + version: "7.6.0" + analyzer_plugin: + dependency: transitive + description: + name: analyzer_plugin + sha256: a5ab7590c27b779f3d4de67f31c4109dbe13dd7339f86461a6f2a8ab2594d8ce + url: "https://pub.dev" + source: hosted + version: "0.13.4" + args: + dependency: transitive + description: + name: args + sha256: d0481093c50b1da8910eb0bb301626d4d8eb7284aa739614d2b394ee09e3ea04 + url: "https://pub.dev" + source: hosted + version: "2.7.0" async: dependency: transitive description: @@ -17,14 +49,102 @@ packages: url: "https://pub.dev" source: hosted version: "2.1.2" + build: + dependency: transitive + description: + name: build + sha256: "51dc711996cbf609b90cbe5b335bbce83143875a9d58e4b5c6d3c4f684d3dda7" + url: "https://pub.dev" + source: hosted + version: "2.5.4" + build_config: + dependency: transitive + description: + name: build_config + sha256: "4ae2de3e1e67ea270081eaee972e1bd8f027d459f249e0f1186730784c2e7e33" + url: "https://pub.dev" + source: hosted + version: "1.1.2" + build_daemon: + dependency: transitive + description: + name: build_daemon + sha256: bf05f6e12cfea92d3c09308d7bcdab1906cd8a179b023269eed00c071004b957 + url: "https://pub.dev" + source: hosted + version: "4.1.1" + build_resolvers: + dependency: transitive + description: + name: build_resolvers + sha256: ee4257b3f20c0c90e72ed2b57ad637f694ccba48839a821e87db762548c22a62 + url: "https://pub.dev" + source: hosted + version: "2.5.4" + build_runner: + dependency: "direct dev" + description: + name: build_runner + sha256: "382a4d649addbfb7ba71a3631df0ec6a45d5ab9b098638144faf27f02778eb53" + url: "https://pub.dev" + source: hosted + version: "2.5.4" + build_runner_core: + dependency: transitive + description: + name: build_runner_core + sha256: "85fbbb1036d576d966332a3f5ce83f2ce66a40bea1a94ad2d5fc29a19a0d3792" + url: "https://pub.dev" + source: hosted + version: "9.1.2" + built_collection: + dependency: transitive + description: + name: built_collection + sha256: "376e3dd27b51ea877c28d525560790aee2e6fbb5f20e2f85d5081027d94e2100" + url: "https://pub.dev" + source: hosted + version: "5.1.1" + built_value: + dependency: transitive + description: + name: built_value + sha256: "6ae8a6435a8c6520c7077b107e77f1fb4ba7009633259a4d49a8afd8e7efc5e9" + url: "https://pub.dev" + source: hosted + version: "8.12.4" characters: dependency: transitive description: name: characters - sha256: f71061c654a3380576a52b451dd5532377954cf9dbd272a78fc8479606670803 + sha256: faf38497bda5ead2a8c7615f4f7939df04333478bf32e4173fcb06d428b5716b + url: "https://pub.dev" + source: hosted + version: "1.4.1" + charcode: + dependency: transitive + description: + name: charcode + sha256: fb0f1107cac15a5ea6ef0a6ef71a807b9e4267c713bb93e00e92d737cc8dbd8a url: "https://pub.dev" source: hosted version: "1.4.0" + checked_yaml: + dependency: transitive + description: + name: checked_yaml + sha256: "959525d3162f249993882720d52b7e0c833978df229be20702b33d48d91de70f" + url: "https://pub.dev" + source: hosted + version: "2.0.4" + cli_util: + dependency: transitive + description: + name: cli_util + sha256: ff6785f7e9e3c38ac98b2fb035701789de90154024a75b6cb926445e83197d1c + url: "https://pub.dev" + source: hosted + version: "0.4.2" clock: dependency: transitive description: @@ -33,6 +153,22 @@ packages: url: "https://pub.dev" source: hosted version: "1.1.2" + code_assets: + dependency: transitive + description: + name: code_assets + sha256: "83ccdaa064c980b5596c35dd64a8d3ecc68620174ab9b90b6343b753aa721687" + url: "https://pub.dev" + source: hosted + version: "1.0.0" + code_builder: + dependency: transitive + description: + name: code_builder + sha256: "6a6cab2ba4680d6423f34a9b972a4c9a94ebe1b62ecec4e1a1f2cba91fd1319d" + url: "https://pub.dev" + source: hosted + version: "4.11.1" collection: dependency: transitive description: @@ -41,6 +177,94 @@ packages: url: "https://pub.dev" source: hosted version: "1.19.1" + convert: + dependency: transitive + description: + name: convert + sha256: b30acd5944035672bc15c6b7a8b47d773e41e2f17de064350988c5d02adb1c68 + url: "https://pub.dev" + source: hosted + version: "3.1.2" + crypto: + dependency: transitive + description: + name: crypto + sha256: c8ea0233063ba03258fbcf2ca4d6dadfefe14f02fab57702265467a19f27fadf + url: "https://pub.dev" + source: hosted + version: "3.0.7" + custom_lint_core: + dependency: transitive + description: + name: custom_lint_core + sha256: "31110af3dde9d29fb10828ca33f1dce24d2798477b167675543ce3d208dee8be" + url: "https://pub.dev" + source: hosted + version: "0.7.5" + custom_lint_visitor: + dependency: transitive + description: + name: custom_lint_visitor + sha256: "4a86a0d8415a91fbb8298d6ef03e9034dc8e323a599ddc4120a0e36c433983a2" + url: "https://pub.dev" + source: hosted + version: "1.0.0+7.7.0" + dart_style: + dependency: transitive + description: + name: dart_style + sha256: "8a0e5fba27e8ee025d2ffb4ee820b4e6e2cf5e4246a6b1a477eb66866947e0bb" + url: "https://pub.dev" + source: hosted + version: "3.1.1" + dbus: + dependency: transitive + description: + name: dbus + sha256: d0c98dcd4f5169878b6cf8f6e0a52403a9dff371a3e2f019697accbf6f44a270 + url: "https://pub.dev" + source: hosted + version: "0.7.12" + dispose_scope: + dependency: transitive + description: + name: dispose_scope + sha256: "48ec38ca2631c53c4f8fa96b294c801e55c335db5e3fb9f82cede150cfe5a2af" + url: "https://pub.dev" + source: hosted + version: "2.1.0" + drift: + dependency: "direct main" + description: + name: drift + sha256: "540cf382a3bfa99b76e51514db5b0ebcd81ce3679b7c1c9cb9478ff3735e47a1" + url: "https://pub.dev" + source: hosted + version: "2.28.2" + drift_dev: + dependency: "direct dev" + description: + name: drift_dev + sha256: "68c138e884527d2bd61df2ade276c3a144df84d1adeb0ab8f3196b5afe021bd4" + url: "https://pub.dev" + source: hosted + version: "2.28.0" + drift_flutter: + dependency: "direct main" + description: + name: drift_flutter + sha256: b7534bf320aac5213259aac120670ba67b63a1fd010505babc436ff86083818f + url: "https://pub.dev" + source: hosted + version: "0.2.7" + equatable: + dependency: transitive + description: + name: equatable + sha256: "3e0141505477fd8ad55d6eb4e7776d3fe8430be8e497ccb1521370c3f21a3e2b" + url: "https://pub.dev" + source: hosted + version: "2.0.8" fake_async: dependency: transitive description: @@ -49,11 +273,40 @@ packages: url: "https://pub.dev" source: hosted version: "1.3.3" + ffi: + dependency: transitive + description: + name: ffi + sha256: "6d7fd89431262d8f3125e81b50d3847a091d846eafcd4fdb88dd06f36d705a45" + url: "https://pub.dev" + source: hosted + version: "2.2.0" + file: + dependency: transitive + description: + name: file + sha256: a3b4f84adafef897088c160faf7dfffb7696046cb13ae90b508c2cbc95d3b8d4 + url: "https://pub.dev" + source: hosted + version: "7.0.1" + fixnum: + dependency: transitive + description: + name: fixnum + sha256: b6dc7065e46c974bc7c5f143080a6764ec7a4be6da1285ececdc37be96de53be + url: "https://pub.dev" + source: hosted + version: "1.1.1" flutter: dependency: "direct main" description: flutter source: sdk version: "0.0.0" + flutter_driver: + dependency: transitive + description: flutter + source: sdk + version: "0.0.0" flutter_lints: dependency: "direct dev" description: @@ -62,11 +315,258 @@ packages: url: "https://pub.dev" source: hosted version: "3.0.2" + flutter_local_notifications: + dependency: "direct main" + description: + name: flutter_local_notifications + sha256: "674173fd3c9eda9d4c8528da2ce0ea69f161577495a9cc835a2a4ecd7eadeb35" + url: "https://pub.dev" + source: hosted + version: "17.2.4" + flutter_local_notifications_linux: + dependency: transitive + description: + name: flutter_local_notifications_linux + sha256: c49bd06165cad9beeb79090b18cd1eb0296f4bf4b23b84426e37dd7c027fc3af + url: "https://pub.dev" + source: hosted + version: "4.0.1" + flutter_local_notifications_platform_interface: + dependency: transitive + description: + name: flutter_local_notifications_platform_interface + sha256: "85f8d07fe708c1bdcf45037f2c0109753b26ae077e9d9e899d55971711a4ea66" + url: "https://pub.dev" + source: hosted + version: "7.2.0" + flutter_markdown: + dependency: "direct main" + description: + name: flutter_markdown + sha256: "08fb8315236099ff8e90cb87bb2b935e0a724a3af1623000a9cec930468e0f27" + url: "https://pub.dev" + source: hosted + version: "0.7.7+1" + flutter_riverpod: + dependency: "direct main" + description: + name: flutter_riverpod + sha256: "9532ee6db4a943a1ed8383072a2e3eeda041db5657cdf6d2acecf3c21ecbe7e1" + url: "https://pub.dev" + source: hosted + version: "2.6.1" + flutter_secure_storage: + dependency: "direct main" + description: + name: flutter_secure_storage + sha256: "9cad52d75ebc511adfae3d447d5d13da15a55a92c9410e50f67335b6d21d16ea" + url: "https://pub.dev" + source: hosted + version: "9.2.4" + flutter_secure_storage_linux: + dependency: transitive + description: + name: flutter_secure_storage_linux + sha256: be76c1d24a97d0b98f8b54bce6b481a380a6590df992d0098f868ad54dc8f688 + url: "https://pub.dev" + source: hosted + version: "1.2.3" + flutter_secure_storage_macos: + dependency: transitive + description: + name: flutter_secure_storage_macos + sha256: "6c0a2795a2d1de26ae202a0d78527d163f4acbb11cde4c75c670f3a0fc064247" + url: "https://pub.dev" + source: hosted + version: "3.1.3" + flutter_secure_storage_platform_interface: + dependency: transitive + description: + name: flutter_secure_storage_platform_interface + sha256: cf91ad32ce5adef6fba4d736a542baca9daf3beac4db2d04be350b87f69ac4a8 + url: "https://pub.dev" + source: hosted + version: "1.1.2" + flutter_secure_storage_web: + dependency: transitive + description: + name: flutter_secure_storage_web + sha256: f4ebff989b4f07b2656fb16b47852c0aab9fed9b4ec1c70103368337bc1886a9 + url: "https://pub.dev" + source: hosted + version: "1.2.1" + flutter_secure_storage_windows: + dependency: transitive + description: + name: flutter_secure_storage_windows + sha256: b20b07cb5ed4ed74fc567b78a72936203f587eba460af1df11281c9326cd3709 + url: "https://pub.dev" + source: hosted + version: "3.1.2" flutter_test: dependency: "direct dev" description: flutter source: sdk version: "0.0.0" + flutter_web_plugins: + dependency: transitive + description: flutter + source: sdk + version: "0.0.0" + freezed: + dependency: "direct dev" + description: + name: freezed + sha256: "59a584c24b3acdc5250bb856d0d3e9c0b798ed14a4af1ddb7dc1c7b41df91c9c" + url: "https://pub.dev" + source: hosted + version: "2.5.8" + freezed_annotation: + dependency: "direct main" + description: + name: freezed_annotation + sha256: c2e2d632dd9b8a2b7751117abcfc2b4888ecfe181bd9fca7170d9ef02e595fe2 + url: "https://pub.dev" + source: hosted + version: "2.4.4" + frontend_server_client: + dependency: transitive + description: + name: frontend_server_client + sha256: f64a0333a82f30b0cca061bc3d143813a486dc086b574bfb233b7c1372427694 + url: "https://pub.dev" + source: hosted + version: "4.0.0" + fuchsia_remote_debug_protocol: + dependency: transitive + description: flutter + source: sdk + version: "0.0.0" + glob: + dependency: transitive + description: + name: glob + sha256: c3f1ee72c96f8f78935e18aa8cecced9ab132419e8625dc187e1c2408efc20de + url: "https://pub.dev" + source: hosted + version: "2.1.3" + go_router: + dependency: "direct main" + description: + name: go_router + sha256: f02fd7d2a4dc512fec615529824fdd217fecb3a3d3de68360293a551f21634b3 + url: "https://pub.dev" + source: hosted + version: "14.8.1" + graphs: + dependency: transitive + description: + name: graphs + sha256: "741bbf84165310a68ff28fe9e727332eef1407342fca52759cb21ad8177bb8d0" + url: "https://pub.dev" + source: hosted + version: "2.3.2" + hive: + dependency: transitive + description: + name: hive + sha256: "8dcf6db979d7933da8217edcec84e9df1bdb4e4edc7fc77dbd5aa74356d6d941" + url: "https://pub.dev" + source: hosted + version: "2.2.3" + hive_flutter: + dependency: "direct main" + description: + name: hive_flutter + sha256: dca1da446b1d808a51689fb5d0c6c9510c0a2ba01e22805d492c73b68e33eecc + url: "https://pub.dev" + source: hosted + version: "1.1.0" + hooks: + dependency: transitive + description: + name: hooks + sha256: e79ed1e8e1929bc6ecb6ec85f0cb519c887aa5b423705ded0d0f2d9226def388 + url: "https://pub.dev" + source: hosted + version: "1.0.2" + http: + dependency: transitive + description: + name: http + sha256: "87721a4a50b19c7f1d49001e51409bddc46303966ce89a65af4f4e6004896412" + url: "https://pub.dev" + source: hosted + version: "1.6.0" + http_multi_server: + dependency: transitive + description: + name: http_multi_server + sha256: aa6199f908078bb1c5efb8d8638d4ae191aac11b311132c3ef48ce352fb52ef8 + url: "https://pub.dev" + source: hosted + version: "3.2.2" + http_parser: + dependency: transitive + description: + name: http_parser + sha256: "178d74305e7866013777bab2c3d8726205dc5a4dd935297175b19a23a2e66571" + url: "https://pub.dev" + source: hosted + version: "4.1.2" + integration_test: + dependency: "direct dev" + description: flutter + source: sdk + version: "0.0.0" + intl: + dependency: "direct main" + description: + name: intl + sha256: d6f56758b7d3014a48af9701c085700aac781a92a87a62b1333b46d8879661cf + url: "https://pub.dev" + source: hosted + version: "0.19.0" + io: + dependency: transitive + description: + name: io + sha256: dfd5a80599cf0165756e3181807ed3e77daf6dd4137caaad72d0b7931597650b + url: "https://pub.dev" + source: hosted + version: "1.0.5" + jni: + dependency: transitive + description: + name: jni + sha256: d2c361082d554d4593c3012e26f6b188f902acd291330f13d6427641a92b3da1 + url: "https://pub.dev" + source: hosted + version: "0.14.2" + js: + dependency: transitive + description: + name: js + sha256: f2c445dce49627136094980615a031419f7f3eb393237e4ecd97ac15dea343f3 + url: "https://pub.dev" + source: hosted + version: "0.6.7" + json_annotation: + dependency: "direct main" + description: + name: json_annotation + sha256: "1ce844379ca14835a50d2f019a3099f419082cfdd231cd86a142af94dd5c6bb1" + url: "https://pub.dev" + source: hosted + version: "4.9.0" + json_serializable: + dependency: "direct dev" + description: + name: json_serializable + sha256: c50ef5fc083d5b5e12eef489503ba3bf5ccc899e487d691584699b4bdefeea8c + url: "https://pub.dev" + source: hosted + version: "6.9.5" leak_tracker: dependency: transitive description: @@ -99,22 +599,38 @@ packages: url: "https://pub.dev" source: hosted version: "3.0.0" + logging: + dependency: transitive + description: + name: logging + sha256: c8245ada5f1717ed44271ed1c26b8ce85ca3228fd2ffdb75468ab01979309d61 + url: "https://pub.dev" + source: hosted + version: "1.3.0" + markdown: + dependency: transitive + description: + name: markdown + sha256: "935e23e1ff3bc02d390bad4d4be001208ee92cc217cb5b5a6c19bc14aaa318c1" + url: "https://pub.dev" + source: hosted + version: "7.3.0" matcher: dependency: transitive description: name: matcher - sha256: dc58c723c3c24bf8d3e2d3ad3f2f9d7bd9cf43ec6feaa64181775e60190153f2 + sha256: dc0b7dc7651697ea4ff3e69ef44b0407ea32c487a39fff6a4004fa585e901861 url: "https://pub.dev" source: hosted - version: "0.12.17" + version: "0.12.19" material_color_utilities: dependency: transitive description: name: material_color_utilities - sha256: f7142bb1154231d7ea5f96bc7bde4bda2a0945d2806bb11670e30b850d56bdec + sha256: "9c337007e82b1889149c82ed242ed1cb24a66044e30979c44912381e9be4c48b" url: "https://pub.dev" source: hosted - version: "0.11.1" + version: "0.13.0" meta: dependency: transitive description: @@ -123,6 +639,70 @@ packages: url: "https://pub.dev" source: hosted version: "1.17.0" + mime: + dependency: transitive + description: + name: mime + sha256: "41a20518f0cb1256669420fdba0cd90d21561e560ac240f26ef8322e45bb7ed6" + url: "https://pub.dev" + source: hosted + version: "2.0.0" + mobile_scanner: + dependency: "direct main" + description: + name: mobile_scanner + sha256: c92c26bf2231695b6d3477c8dcf435f51e28f87b1745966b1fe4c47a286171ce + url: "https://pub.dev" + source: hosted + version: "7.2.0" + mockito: + dependency: "direct dev" + description: + name: mockito + sha256: "4546eac99e8967ea91bae633d2ca7698181d008e95fa4627330cf903d573277a" + url: "https://pub.dev" + source: hosted + version: "5.4.6" + native_toolchain_c: + dependency: transitive + description: + name: native_toolchain_c + sha256: "6ba77bb18063eebe9de401f5e6437e95e1438af0a87a3a39084fbd37c90df572" + url: "https://pub.dev" + source: hosted + version: "0.17.6" + objective_c: + dependency: transitive + description: + name: objective_c + sha256: "100a1c87616ab6ed41ec263b083c0ef3261ee6cd1dc3b0f35f8ddfa4f996fe52" + url: "https://pub.dev" + source: hosted + version: "9.3.0" + package_config: + dependency: transitive + description: + name: package_config + sha256: f096c55ebb7deb7e384101542bfba8c52696c1b56fca2eb62827989ef2353bbc + url: "https://pub.dev" + source: hosted + version: "2.2.0" + package_info_plus: + dependency: transitive + description: + name: package_info_plus + sha256: f69da0d3189a4b4ceaeb1a3defb0f329b3b352517f52bed4290f83d4f06bc08d + url: "https://pub.dev" + source: hosted + version: "9.0.0" + package_info_plus_platform_interface: + dependency: transitive + description: + name: package_info_plus_platform_interface + sha256: "202a487f08836a592a6bd4f901ac69b3a8f146af552bbd14407b6b41e1c3f086" + url: "https://pub.dev" + source: hosted + version: "3.2.1" path: dependency: transitive description: @@ -131,11 +711,235 @@ packages: url: "https://pub.dev" source: hosted version: "1.9.1" + path_provider: + dependency: transitive + description: + name: path_provider + sha256: "50c5dd5b6e1aaf6fb3a78b33f6aa3afca52bf903a8a5298f53101fdaee55bbcd" + url: "https://pub.dev" + source: hosted + version: "2.1.5" + path_provider_android: + dependency: transitive + description: + name: path_provider_android + sha256: f2c65e21139ce2c3dad46922be8272bb5963516045659e71bb16e151c93b580e + url: "https://pub.dev" + source: hosted + version: "2.2.22" + path_provider_foundation: + dependency: transitive + description: + name: path_provider_foundation + sha256: "2a376b7d6392d80cd3705782d2caa734ca4727776db0b6ec36ef3f1855197699" + url: "https://pub.dev" + source: hosted + version: "2.6.0" + path_provider_linux: + dependency: transitive + description: + name: path_provider_linux + sha256: f7a1fe3a634fe7734c8d3f2766ad746ae2a2884abe22e241a8b301bf5cac3279 + url: "https://pub.dev" + source: hosted + version: "2.2.1" + path_provider_platform_interface: + dependency: transitive + description: + name: path_provider_platform_interface + sha256: "88f5779f72ba699763fa3a3b06aa4bf6de76c8e5de842cf6f29e2e06476c2334" + url: "https://pub.dev" + source: hosted + version: "2.1.2" + path_provider_windows: + dependency: transitive + description: + name: path_provider_windows + sha256: bd6f00dbd873bfb70d0761682da2b3a2c2fccc2b9e84c495821639601d81afe7 + url: "https://pub.dev" + source: hosted + version: "2.3.0" + patrol: + dependency: "direct dev" + description: + name: patrol + sha256: "32fd0709f3871fa56eb9cd88410e3ca816bfa757122bae806a0f842188acb820" + url: "https://pub.dev" + source: hosted + version: "3.20.0" + patrol_finders: + dependency: transitive + description: + name: patrol_finders + sha256: "4a658d7d560de523f92deb3fa3326c78747ca0bf7e7f4b8788c012463138b628" + url: "https://pub.dev" + source: hosted + version: "2.9.0" + patrol_log: + dependency: transitive + description: + name: patrol_log + sha256: "9fed4143980df1e3bbcfa00d0b443c7d68f04f9132317b7698bbc37f8a5a58c5" + url: "https://pub.dev" + source: hosted + version: "0.5.0" + pedantic: + dependency: transitive + description: + name: pedantic + sha256: "67fc27ed9639506c856c840ccce7594d0bdcd91bc8d53d6e52359449a1d50602" + url: "https://pub.dev" + source: hosted + version: "1.11.1" + petitparser: + dependency: transitive + description: + name: petitparser + sha256: "91bd59303e9f769f108f8df05e371341b15d59e995e6806aefab827b58336675" + url: "https://pub.dev" + source: hosted + version: "7.0.2" + platform: + dependency: transitive + description: + name: platform + sha256: "5d6b1b0036a5f331ebc77c850ebc8506cbc1e9416c27e59b439f917a902a4984" + url: "https://pub.dev" + source: hosted + version: "3.1.6" + plugin_platform_interface: + dependency: transitive + description: + name: plugin_platform_interface + sha256: "4820fbfdb9478b1ebae27888254d445073732dae3d6ea81f0b7e06d5dedc3f02" + url: "https://pub.dev" + source: hosted + version: "2.1.8" + pool: + dependency: transitive + description: + name: pool + sha256: "978783255c543aa3586a1b3c21f6e9d720eb315376a915872c61ef8b5c20177d" + url: "https://pub.dev" + source: hosted + version: "1.5.2" + process: + dependency: transitive + description: + name: process + sha256: c6248e4526673988586e8c00bb22a49210c258dc91df5227d5da9748ecf79744 + url: "https://pub.dev" + source: hosted + version: "5.0.5" + pub_semver: + dependency: transitive + description: + name: pub_semver + sha256: "5bfcf68ca79ef689f8990d1160781b4bad40a3bd5e5218ad4076ddb7f4081585" + url: "https://pub.dev" + source: hosted + version: "2.2.0" + pubspec_parse: + dependency: transitive + description: + name: pubspec_parse + sha256: "0560ba233314abbed0a48a2956f7f022cce7c3e1e73df540277da7544cad4082" + url: "https://pub.dev" + source: hosted + version: "1.5.0" + recase: + dependency: transitive + description: + name: recase + sha256: e4eb4ec2dcdee52dcf99cb4ceabaffc631d7424ee55e56f280bc039737f89213 + url: "https://pub.dev" + source: hosted + version: "4.1.0" + riverpod: + dependency: transitive + description: + name: riverpod + sha256: "59062512288d3056b2321804332a13ffdd1bf16df70dcc8e506e411280a72959" + url: "https://pub.dev" + source: hosted + version: "2.6.1" + riverpod_analyzer_utils: + dependency: transitive + description: + name: riverpod_analyzer_utils + sha256: "837a6dc33f490706c7f4632c516bcd10804ee4d9ccc8046124ca56388715fdf3" + url: "https://pub.dev" + source: hosted + version: "0.5.9" + riverpod_annotation: + dependency: "direct main" + description: + name: riverpod_annotation + sha256: e14b0bf45b71326654e2705d462f21b958f987087be850afd60578fcd502d1b8 + url: "https://pub.dev" + source: hosted + version: "2.6.1" + riverpod_generator: + dependency: "direct dev" + description: + name: riverpod_generator + sha256: "120d3310f687f43e7011bb213b90a436f1bbc300f0e4b251a72c39bccb017a4f" + url: "https://pub.dev" + source: hosted + version: "2.6.4" + sentry: + dependency: transitive + description: + name: sentry + sha256: "605ad1f6f1ae5b72018cbe8fc20f490fa3bd53e58882e5579566776030d8c8c1" + url: "https://pub.dev" + source: hosted + version: "9.14.0" + sentry_flutter: + dependency: "direct main" + description: + name: sentry_flutter + sha256: "7fd0fb80050c1f6a77ae185bda997a76d384326d6777cf5137a6c38952c4ac7d" + url: "https://pub.dev" + source: hosted + version: "9.14.0" + shelf: + dependency: transitive + description: + name: shelf + sha256: e7dd780a7ffb623c57850b33f43309312fc863fb6aa3d276a754bb299839ef12 + url: "https://pub.dev" + source: hosted + version: "1.4.2" + shelf_web_socket: + dependency: transitive + description: + name: shelf_web_socket + sha256: "3632775c8e90d6c9712f883e633716432a27758216dfb61bd86a8321c0580925" + url: "https://pub.dev" + source: hosted + version: "3.0.0" sky_engine: dependency: transitive description: flutter source: sdk version: "0.0.0" + source_gen: + dependency: transitive + description: + name: source_gen + sha256: "35c8150ece9e8c8d263337a265153c3329667640850b9304861faea59fc98f6b" + url: "https://pub.dev" + source: hosted + version: "2.0.0" + source_helper: + dependency: transitive + description: + name: source_helper + sha256: a447acb083d3a5ef17f983dd36201aeea33fedadb3228fa831f2f0c92f0f3aca + url: "https://pub.dev" + source: hosted + version: "1.3.7" source_span: dependency: transitive description: @@ -144,6 +948,54 @@ packages: url: "https://pub.dev" source: hosted version: "1.10.2" + speech_to_text: + dependency: "direct main" + description: + name: speech_to_text + sha256: c07557664974afa061f221d0d4186935bea4220728ea9446702825e8b988db04 + url: "https://pub.dev" + source: hosted + version: "7.3.0" + speech_to_text_platform_interface: + dependency: transitive + description: + name: speech_to_text_platform_interface + sha256: a1935847704e41ee468aad83181ddd2423d0833abe55d769c59afca07adb5114 + url: "https://pub.dev" + source: hosted + version: "2.3.0" + speech_to_text_windows: + dependency: transitive + description: + name: speech_to_text_windows + sha256: "2c9846d18253c7bbe059a276297ef9f27e8a2745dead32192525beb208195072" + url: "https://pub.dev" + source: hosted + version: "1.0.0+beta.8" + sqlite3: + dependency: transitive + description: + name: sqlite3 + sha256: "3145bd74dcdb4fd6f5c6dda4d4e4490a8087d7f286a14dee5d37087290f0f8a2" + url: "https://pub.dev" + source: hosted + version: "2.9.4" + sqlite3_flutter_libs: + dependency: "direct main" + description: + name: sqlite3_flutter_libs + sha256: eeb9e3a45207649076b808f8a5a74d68770d0b7f26ccef6d5f43106eee5375ad + url: "https://pub.dev" + source: hosted + version: "0.5.42" + sqlparser: + dependency: transitive + description: + name: sqlparser + sha256: "57090342af1ce32bb499aa641f4ecdd2d6231b9403cea537ac059e803cc20d67" + url: "https://pub.dev" + source: hosted + version: "0.41.2" stack_trace: dependency: transitive description: @@ -152,6 +1004,14 @@ packages: url: "https://pub.dev" source: hosted version: "1.12.1" + state_notifier: + dependency: transitive + description: + name: state_notifier + sha256: b8677376aa54f2d7c58280d5a007f9e8774f1968d1fb1c096adcb4792fba29bb + url: "https://pub.dev" + source: hosted + version: "1.0.0" stream_channel: dependency: transitive description: @@ -160,6 +1020,14 @@ packages: url: "https://pub.dev" source: hosted version: "2.1.4" + stream_transform: + dependency: transitive + description: + name: stream_transform + sha256: ad47125e588cfd37a9a7f86c7d6356dde8dfe89d071d293f80ca9e9273a33871 + url: "https://pub.dev" + source: hosted + version: "2.1.1" string_scanner: dependency: transitive description: @@ -168,6 +1036,14 @@ packages: url: "https://pub.dev" source: hosted version: "1.4.1" + sync_http: + dependency: transitive + description: + name: sync_http + sha256: "7f0cd72eca000d2e026bcd6f990b81d0ca06022ef4e32fb257b30d3d1014a961" + url: "https://pub.dev" + source: hosted + version: "0.3.1" term_glyph: dependency: transitive description: @@ -180,10 +1056,42 @@ packages: dependency: transitive description: name: test_api - sha256: ab2726c1a94d3176a45960b6234466ec367179b87dd74f1611adb1f3b5fb9d55 + sha256: "8161c84903fd860b26bfdefb7963b3f0b68fee7adea0f59ef805ecca346f0c7a" + url: "https://pub.dev" + source: hosted + version: "0.7.10" + timezone: + dependency: transitive + description: + name: timezone + sha256: "2236ec079a174ce07434e89fcd3fcda430025eb7692244139a9cf54fdcf1fc7d" + url: "https://pub.dev" + source: hosted + version: "0.9.4" + timing: + dependency: transitive + description: + name: timing + sha256: "62ee18aca144e4a9f29d212f5a4c6a053be252b895ab14b5821996cff4ed90fe" + url: "https://pub.dev" + source: hosted + version: "1.0.2" + typed_data: + dependency: transitive + description: + name: typed_data + sha256: f9049c039ebfeb4cf7a7104a675823cd72dba8297f264b6637062516699fa006 + url: "https://pub.dev" + source: hosted + version: "1.4.0" + uuid: + dependency: "direct main" + description: + name: uuid + sha256: "1fef9e8e11e2991bb773070d4656b7bd5d850967a2456cfc83cf47925ba79489" url: "https://pub.dev" source: hosted - version: "0.7.7" + version: "4.5.3" vector_math: dependency: transitive description: @@ -200,6 +1108,78 @@ packages: url: "https://pub.dev" source: hosted version: "15.0.2" + watcher: + dependency: transitive + description: + name: watcher + sha256: "1398c9f081a753f9226febe8900fce8f7d0a67163334e1c94a2438339d79d635" + url: "https://pub.dev" + source: hosted + version: "1.2.1" + web: + dependency: transitive + description: + name: web + sha256: "868d88a33d8a87b18ffc05f9f030ba328ffefba92d6c127917a2ba740f9cfe4a" + url: "https://pub.dev" + source: hosted + version: "1.1.1" + web_socket: + dependency: transitive + description: + name: web_socket + sha256: "34d64019aa8e36bf9842ac014bb5d2f5586ca73df5e4d9bf5c936975cae6982c" + url: "https://pub.dev" + source: hosted + version: "1.0.1" + web_socket_channel: + dependency: "direct main" + description: + name: web_socket_channel + sha256: d645757fb0f4773d602444000a8131ff5d48c9e47adfe9772652dd1a4f2d45c8 + url: "https://pub.dev" + source: hosted + version: "3.0.3" + webdriver: + dependency: transitive + description: + name: webdriver + sha256: "2f3a14ca026957870cfd9c635b83507e0e51d8091568e90129fbf805aba7cade" + url: "https://pub.dev" + source: hosted + version: "3.1.0" + win32: + dependency: transitive + description: + name: win32 + sha256: d7cb55e04cd34096cd3a79b3330245f54cb96a370a1c27adb3c84b917de8b08e + url: "https://pub.dev" + source: hosted + version: "5.15.0" + xdg_directories: + dependency: transitive + description: + name: xdg_directories + sha256: "7a3f37b05d989967cdddcbb571f1ea834867ae2faa29725fd085180e0883aa15" + url: "https://pub.dev" + source: hosted + version: "1.1.0" + xml: + dependency: transitive + description: + name: xml + sha256: "971043b3a0d3da28727e40ed3e0b5d18b742fa5a68665cca88e74b7876d5e025" + url: "https://pub.dev" + source: hosted + version: "6.6.1" + yaml: + dependency: transitive + description: + name: yaml + sha256: b9da305ac7c39faa3f030eccd175340f968459dae4af175130b3fc47e40d76ce + url: "https://pub.dev" + source: hosted + version: "3.1.3" sdks: - dart: ">=3.8.0-0 <4.0.0" - flutter: ">=3.18.0-18.0.pre.54" + dart: ">=3.10.3 <4.0.0" + flutter: ">=3.38.4" diff --git a/apps/mobile/pubspec.yaml b/apps/mobile/pubspec.yaml index 020e5e6..5999c73 100644 --- a/apps/mobile/pubspec.yaml +++ b/apps/mobile/pubspec.yaml @@ -1,12 +1,8 @@ name: recursor_mobile - -description: ReCursor Flutter mobile app (scaffold only). +description: ReCursor Flutter mobile app — OpenCode-style UI for AI coding agents. repository: https://github.com/RecursiveDev/ReCursor - -# Prevent accidental publishing. publish_to: "none" - -version: 0.0.0 +version: 0.1.0+1 environment: sdk: ">=3.3.0 <4.0.0" @@ -15,10 +11,72 @@ dependencies: flutter: sdk: flutter + # State management + flutter_riverpod: ^2.5.1 + riverpod_annotation: ^2.3.5 + + # Immutable models + freezed_annotation: ^2.4.4 + json_annotation: ^4.9.0 + + # Local database + drift: ^2.18.0 + drift_flutter: ^0.2.0 + sqlite3_flutter_libs: ^0.5.0 + + # Key-value cache + hive_flutter: ^1.1.0 + + # Networking + web_socket_channel: ^3.0.0 + + # Secure storage + flutter_secure_storage: ^9.2.2 + + # Navigation + go_router: ^14.2.0 + + # Markdown rendering + flutter_markdown: ^0.7.4 + + # QR scanning + mobile_scanner: ^7.2.0 + + # Voice input + speech_to_text: ^7.3.0 + + # Local notifications + flutter_local_notifications: ^17.2.2 + + # Crash reporting + sentry_flutter: ^9.14.0 + + # Utilities + uuid: ^4.4.0 + intl: ^0.19.0 + dev_dependencies: flutter_test: sdk: flutter + integration_test: + sdk: flutter flutter_lints: ^3.0.0 + build_runner: ^2.4.11 + freezed: ^2.5.7 + riverpod_generator: ^2.4.3 + drift_dev: ^2.18.0 + json_serializable: ^6.8.0 + mockito: ^5.4.4 + patrol: ^3.14.0 flutter: uses-material-design: true + assets: + - assets/branding/ + - assets/fonts/ + fonts: + - family: JetBrainsMono + fonts: + - asset: assets/fonts/JetBrainsMono-Regular.ttf + - asset: assets/fonts/JetBrainsMono-Bold.ttf + weight: 700 diff --git a/apps/mobile/test/widget_test.dart b/apps/mobile/test/widget_test.dart new file mode 100644 index 0000000..296fe28 --- /dev/null +++ b/apps/mobile/test/widget_test.dart @@ -0,0 +1,30 @@ +// This is a basic Flutter widget test. +// +// To perform an interaction with a widget in your test, use the WidgetTester +// utility in the flutter_test package. For example, you can send tap and scroll +// gestures. You can also use WidgetTester to find child widgets in the widget +// tree, read text, and verify that the values of widget properties are correct. + +import 'package:flutter/material.dart'; +import 'package:flutter_test/flutter_test.dart'; + +import 'package:recursor_mobile/main.dart'; + +void main() { + testWidgets('Counter increments smoke test', (WidgetTester tester) async { + // Build our app and trigger a frame. + await tester.pumpWidget(const MyApp()); + + // Verify that our counter starts at 0. + expect(find.text('0'), findsOneWidget); + expect(find.text('1'), findsNothing); + + // Tap the '+' icon and trigger a frame. + await tester.tap(find.byIcon(Icons.add)); + await tester.pump(); + + // Verify that our counter has incremented. + expect(find.text('0'), findsNothing); + expect(find.text('1'), findsOneWidget); + }); +} diff --git a/fastlane/Appfile b/fastlane/Appfile new file mode 100644 index 0000000..a4066dc --- /dev/null +++ b/fastlane/Appfile @@ -0,0 +1,10 @@ +app_identifier("dev.recursor.mobile") + +# iOS +apple_id(ENV["APPLE_ID"]) +itc_team_id(ENV["ITC_TEAM_ID"]) +team_id(ENV["TEAM_ID"]) + +# Android +json_key_file(ENV["SUPPLY_JSON_KEY"]) +package_name("dev.recursor.mobile") diff --git a/fastlane/Fastfile b/fastlane/Fastfile new file mode 100644 index 0000000..d5d0a3d --- /dev/null +++ b/fastlane/Fastfile @@ -0,0 +1,81 @@ +fastlane_version "2.220.0" + +default_platform(:ios) + +# ─── iOS ───────────────────────────────────────────────────────────────────── + +platform :ios do + desc "Sync certificates and provisioning profiles (read-only)" + lane :certificates do + match( + type: "appstore", + readonly: true, + app_identifier: "dev.recursor.mobile" + ) + end + + desc "Build release IPA" + lane :build do + match( + type: "appstore", + readonly: true, + app_identifier: "dev.recursor.mobile" + ) + + build_app( + workspace: "apps/mobile/ios/Runner.xcworkspace", + scheme: "Runner", + export_method: "app-store", + output_directory: "apps/mobile/build/ios/iphoneos", + clean: true + ) + end + + desc "Upload to TestFlight" + lane :testflight do + build + upload_to_testflight( + skip_waiting_for_build_processing: true + ) + end + + desc "Submit to App Store" + lane :release do + build + upload_to_app_store( + skip_metadata: false, + skip_screenshots: false, + submit_for_review: false + ) + end +end + +# ─── Android ───────────────────────────────────────────────────────────────── + +platform :android do + desc "Build release App Bundle" + lane :build do + gradle( + task: "bundle", + build_type: "Release", + project_dir: "apps/mobile/android" + ) + end + + desc "Deploy to Play Store internal track" + lane :deploy do + build + upload_to_play_store( + track: "internal", + aab: "apps/mobile/build/app/outputs/bundle/release/app-release.aab" + ) + end + + desc "Promote internal → production" + lane :promote do + upload_to_play_store( + track: "internal", + track_promote_to: "production" + ) + end +end diff --git a/fastlane/Matchfile b/fastlane/Matchfile new file mode 100644 index 0000000..f96d00f --- /dev/null +++ b/fastlane/Matchfile @@ -0,0 +1,4 @@ +git_url(ENV["MATCH_GIT_URL"]) +storage_mode("git") +type("appstore") +app_identifier(["dev.recursor.mobile"]) diff --git a/fastlane/Pluginfile b/fastlane/Pluginfile new file mode 100644 index 0000000..1fb97e8 --- /dev/null +++ b/fastlane/Pluginfile @@ -0,0 +1,5 @@ +# Autogenerated by fastlane +# +# Ensure this file is checked in to source control! + +# gem "fastlane-plugin-example" diff --git a/fastlane/metadata/en-US/description.txt b/fastlane/metadata/en-US/description.txt new file mode 100644 index 0000000..84c6a50 --- /dev/null +++ b/fastlane/metadata/en-US/description.txt @@ -0,0 +1,20 @@ +ReCursor brings your AI coding agent workflows to mobile. Monitor Claude Code sessions, review and approve tool calls, view code diffs, and interact with AI coding agents — all from your iPhone or Android device. + +FEATURES +• Real-time Claude Code session monitoring via hooks integration +• OpenCode-style tool cards showing exactly what your AI agent is doing +• Syntax-highlighted code diff viewer +• Tool call approval flow — approve, reject, or modify AI actions before they execute +• Parallel Agent SDK sessions for direct AI interaction from mobile +• Session timeline with full event history +• Git status, commits, and branch management +• Embedded terminal with ANSI color support +• Multi-agent support: Claude Code, OpenCode, Aider, Goose +• Offline mode with local SQLite storage and sync on reconnect +• Voice-to-text input +• Secure connection via Tailscale/WireGuard mesh VPN + +GETTING STARTED +ReCursor connects to the ReCursor bridge server running on your development machine. Pair via QR code or manual entry. + +Requires: ReCursor bridge server (open source, runs on macOS/Linux/Windows) diff --git a/fastlane/metadata/en-US/keywords.txt b/fastlane/metadata/en-US/keywords.txt new file mode 100644 index 0000000..e35e91e --- /dev/null +++ b/fastlane/metadata/en-US/keywords.txt @@ -0,0 +1 @@ +AI,coding,agent,Claude,developer,mobile,code review,diff viewer,terminal diff --git a/fastlane/metadata/en-US/name.txt b/fastlane/metadata/en-US/name.txt new file mode 100644 index 0000000..822c469 --- /dev/null +++ b/fastlane/metadata/en-US/name.txt @@ -0,0 +1 @@ +ReCursor diff --git a/fastlane/metadata/en-US/privacy_url.txt b/fastlane/metadata/en-US/privacy_url.txt new file mode 100644 index 0000000..55c3c66 --- /dev/null +++ b/fastlane/metadata/en-US/privacy_url.txt @@ -0,0 +1 @@ +https://recursor.dev/privacy diff --git a/fastlane/metadata/en-US/release_notes.txt b/fastlane/metadata/en-US/release_notes.txt new file mode 100644 index 0000000..ee4955f --- /dev/null +++ b/fastlane/metadata/en-US/release_notes.txt @@ -0,0 +1,10 @@ +Initial release of ReCursor — AI Coding Agent companion for mobile. + +• Claude Code session monitoring via hooks +• Tool card approval flow +• Code diff viewer +• Agent chat with streaming responses +• Git operations +• Terminal access +• Voice input +• Offline mode diff --git a/fastlane/metadata/en-US/subtitle.txt b/fastlane/metadata/en-US/subtitle.txt new file mode 100644 index 0000000..6e6e735 --- /dev/null +++ b/fastlane/metadata/en-US/subtitle.txt @@ -0,0 +1 @@ +AI Coding Agent on Mobile diff --git a/fastlane/metadata/en-US/support_url.txt b/fastlane/metadata/en-US/support_url.txt new file mode 100644 index 0000000..8031d24 --- /dev/null +++ b/fastlane/metadata/en-US/support_url.txt @@ -0,0 +1 @@ +https://github.com/RecursiveDev/ReCursor/issues From 894565dc590dcb246071074270c12326f21bbcb6 Mon Sep 17 00:00:00 2001 From: MasuRii Date: Fri, 20 Mar 2026 10:23:34 +0800 Subject: [PATCH 05/22] chore(tool): add development helper scripts for bridge and mobile Add shell/PowerShell scripts for checking and running the bridge server and mobile app with consistent formatting, type checking, and testing. --- tool/bridge-check-and-run.ps1 | 99 ++++++++++++++++++++++++++ tool/bridge-check-and-run.sh | 91 ++++++++++++++++++++++++ tool/install-git-hooks.ps1 | 12 ++++ tool/install-git-hooks.sh | 10 +++ tool/mobile-check-and-run.ps1 | 120 ++++++++++++++++++++++++++++++++ tool/mobile-check-and-run.sh | 126 ++++++++++++++++++++++++++++++++++ 6 files changed, 458 insertions(+) create mode 100644 tool/bridge-check-and-run.ps1 create mode 100644 tool/bridge-check-and-run.sh create mode 100644 tool/install-git-hooks.ps1 create mode 100644 tool/install-git-hooks.sh create mode 100644 tool/mobile-check-and-run.ps1 create mode 100644 tool/mobile-check-and-run.sh diff --git a/tool/bridge-check-and-run.ps1 b/tool/bridge-check-and-run.ps1 new file mode 100644 index 0000000..b76f206 --- /dev/null +++ b/tool/bridge-check-and-run.ps1 @@ -0,0 +1,99 @@ +param( + [switch]$SkipInstall, + [switch]$SkipRun, + [switch]$AllFiles, + [ValidateSet('dev', 'start')] + [string]$RunScript = 'dev' +) + +$ErrorActionPreference = 'Stop' +Set-StrictMode -Version Latest + +function Invoke-Step { + param( + [Parameter(Mandatory = $true)] + [string]$Name, + [Parameter(Mandatory = $true)] + [string]$Executable, + [string[]]$Arguments = @() + ) + + Write-Host "==> $Name" -ForegroundColor Cyan + & $Executable @Arguments + + if ($LASTEXITCODE -ne 0) { + throw "$Name failed with exit code $LASTEXITCODE." + } +} + +function Get-ChangedBridgeFiles { + param( + [Parameter(Mandatory = $true)] + [string]$RepositoryRoot + ) + + $trackedOutput = & git -C $RepositoryRoot diff --name-only --diff-filter=ACMR + if ($LASTEXITCODE -ne 0) { + throw 'Unable to read tracked bridge file changes from git.' + } + + $untrackedOutput = & git -C $RepositoryRoot ls-files --others --exclude-standard + if ($LASTEXITCODE -ne 0) { + throw 'Unable to read untracked bridge file changes from git.' + } + + $files = @($trackedOutput + $untrackedOutput) | + Where-Object { + $_ -match '^packages/bridge/' -and + $_ -notmatch '^packages/bridge/(dist|node_modules)/' -and + $_ -match '\.(ts|js|cjs|mjs|json)$' + } | + Sort-Object -Unique + + return @($files) +} + +$repoRoot = Resolve-Path (Join-Path $PSScriptRoot '..') +$bridgeDir = Join-Path $repoRoot 'packages/bridge' +$nodeModulesDir = Join-Path $bridgeDir 'node_modules' +$changedFiles = @() + +if (-not $AllFiles) { + $changedFiles = @(Get-ChangedBridgeFiles -RepositoryRoot $repoRoot) +} + +$relativeChangedFiles = $changedFiles | ForEach-Object { $_ -replace '^packages/bridge/', '' } + +Push-Location $bridgeDir +try { + if (-not $SkipInstall -and -not (Test-Path $nodeModulesDir)) { + Invoke-Step -Name 'npm ci' -Executable 'npm' -Arguments @('ci') + } + elseif (-not $SkipInstall) { + Write-Host 'node_modules already exists; skipping npm ci. Use a clean install manually when needed.' -ForegroundColor Yellow + } + + if ($AllFiles) { + Invoke-Step -Name 'npm run format' -Executable 'npm' -Arguments @('run', 'format') + } + elseif ($changedFiles.Count -gt 0) { + Invoke-Step -Name 'prettier changed files' -Executable 'npm' -Arguments (@('exec', 'prettier', '--', '--write') + $relativeChangedFiles) + } + else { + Write-Host 'No changed bridge files detected; skipping prettier. Use -AllFiles for a project-wide pass.' -ForegroundColor Yellow + } + + Invoke-Step -Name 'npm run typecheck' -Executable 'npm' -Arguments @('run', 'typecheck') + Invoke-Step -Name 'npm test -- --passWithNoTests --runInBand' -Executable 'npm' -Arguments @('test', '--', '--passWithNoTests', '--runInBand') + Invoke-Step -Name 'npm run build' -Executable 'npm' -Arguments @('run', 'build') + + if ($SkipRun) { + Write-Host 'Skipping npm run because -SkipRun was provided.' -ForegroundColor Yellow + return + } + + Invoke-Step -Name "npm run $RunScript" -Executable 'npm' -Arguments @('run', $RunScript) +} +finally { + Pop-Location +} diff --git a/tool/bridge-check-and-run.sh b/tool/bridge-check-and-run.sh new file mode 100644 index 0000000..ab613e2 --- /dev/null +++ b/tool/bridge-check-and-run.sh @@ -0,0 +1,91 @@ +#!/usr/bin/env bash +set -euo pipefail + +SKIP_INSTALL=false +SKIP_RUN=false +ALL_FILES=false +RUN_SCRIPT="dev" + +while [[ $# -gt 0 ]]; do + case "$1" in + --skip-install) + SKIP_INSTALL=true + shift + ;; + --skip-run) + SKIP_RUN=true + shift + ;; + --all-files) + ALL_FILES=true + shift + ;; + --run-script) + RUN_SCRIPT="$2" + shift 2 + ;; + *) + echo "Unknown argument: $1" >&2 + exit 1 + ;; + esac +done + +run_step() { + local name="$1" + shift + echo "==> $name" + "$@" +} + +SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)" +REPO_ROOT="$(cd "$SCRIPT_DIR/.." && pwd)" +BRIDGE_DIR="$REPO_ROOT/packages/bridge" +NODE_MODULES_DIR="$BRIDGE_DIR/node_modules" + +mapfile -t CHANGED_FILES < <( + if [[ "$ALL_FILES" == true ]]; then + true + else + cd "$REPO_ROOT" + { + git diff --name-only --diff-filter=ACMR + git ls-files --others --exclude-standard + } | grep -E '^packages/bridge/' \ + | grep -Ev '^packages/bridge/(dist|node_modules)/' \ + | grep -E '\.(ts|js|cjs|mjs|json)$' \ + | sort -u || true + fi +) + +RELATIVE_CHANGED_FILES=() +for file in "${CHANGED_FILES[@]}"; do + RELATIVE_CHANGED_FILES+=("${file#packages/bridge/}") +done + +cd "$BRIDGE_DIR" + +if [[ "$SKIP_INSTALL" != true && ! -d "$NODE_MODULES_DIR" ]]; then + run_step "npm ci" npm ci +elif [[ "$SKIP_INSTALL" != true ]]; then + echo "node_modules already exists; skipping npm ci. Use a clean install manually when needed." +fi + +if [[ "$ALL_FILES" == true ]]; then + run_step "npm run format" npm run format +elif [[ ${#CHANGED_FILES[@]} -gt 0 ]]; then + run_step "prettier changed files" npm exec prettier -- --write "${RELATIVE_CHANGED_FILES[@]}" +else + echo "No changed bridge files detected; skipping prettier. Use --all-files for a project-wide pass." +fi + +run_step "npm run typecheck" npm run typecheck +run_step "npm test -- --passWithNoTests --runInBand" npm test -- --passWithNoTests --runInBand +run_step "npm run build" npm run build + +if [[ "$SKIP_RUN" == true ]]; then + echo "Skipping npm run because --skip-run was provided." + exit 0 +fi + +run_step "npm run $RUN_SCRIPT" npm run "$RUN_SCRIPT" diff --git a/tool/install-git-hooks.ps1 b/tool/install-git-hooks.ps1 new file mode 100644 index 0000000..22fbd68 --- /dev/null +++ b/tool/install-git-hooks.ps1 @@ -0,0 +1,12 @@ +$ErrorActionPreference = 'Stop' +Set-StrictMode -Version Latest + +$repoRoot = Resolve-Path (Join-Path $PSScriptRoot '..') +Push-Location $repoRoot +try { + git config core.hooksPath .githooks + Write-Host 'Configured git hooks path to .githooks' -ForegroundColor Green +} +finally { + Pop-Location +} diff --git a/tool/install-git-hooks.sh b/tool/install-git-hooks.sh new file mode 100644 index 0000000..178835e --- /dev/null +++ b/tool/install-git-hooks.sh @@ -0,0 +1,10 @@ +#!/usr/bin/env bash +set -euo pipefail + +SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)" +REPO_ROOT="$(cd "$SCRIPT_DIR/.." && pwd)" + +cd "$REPO_ROOT" +git config core.hooksPath .githooks + +echo "Configured git hooks path to .githooks" diff --git a/tool/mobile-check-and-run.ps1 b/tool/mobile-check-and-run.ps1 new file mode 100644 index 0000000..123f462 --- /dev/null +++ b/tool/mobile-check-and-run.ps1 @@ -0,0 +1,120 @@ +param( + [string]$DeviceId = '', + [switch]$SkipPubGet, + [switch]$SkipRun, + [switch]$StrictAnalyze, + [switch]$ApplyProjectFixes, + [switch]$AllFiles, + [Parameter(ValueFromRemainingArguments = $true)] + [string[]]$FlutterRunArgs = @() +) + +$ErrorActionPreference = 'Stop' +Set-StrictMode -Version Latest + +function Invoke-Step { + param( + [Parameter(Mandatory = $true)] + [string]$Name, + [Parameter(Mandatory = $true)] + [string]$Executable, + [string[]]$Arguments = @() + ) + + Write-Host "==> $Name" -ForegroundColor Cyan + & $Executable @Arguments + + if ($LASTEXITCODE -ne 0) { + throw "$Name failed with exit code $LASTEXITCODE." + } +} + +function Get-ChangedDartFiles { + param( + [Parameter(Mandatory = $true)] + [string]$RepositoryRoot + ) + + $trackedOutput = & git -C $RepositoryRoot diff --name-only --diff-filter=ACMR -- ':(glob)apps/mobile/**/*.dart' + if ($LASTEXITCODE -ne 0) { + throw 'Unable to read tracked Dart file changes from git.' + } + + $untrackedOutput = & git -C $RepositoryRoot ls-files --others --exclude-standard -- ':(glob)apps/mobile/**/*.dart' + if ($LASTEXITCODE -ne 0) { + throw 'Unable to read untracked Dart file changes from git.' + } + + $files = @($trackedOutput + $untrackedOutput) | + Where-Object { $_ -and $_ -notmatch '\.(g|freezed)\.dart$' } | + Sort-Object -Unique + + return @($files) +} + +$repoRoot = Resolve-Path (Join-Path $PSScriptRoot '..') +$appDir = Join-Path $repoRoot 'apps/mobile' +$changedDartFiles = @() + +if (-not $AllFiles) { + $changedDartFiles = @(Get-ChangedDartFiles -RepositoryRoot $repoRoot) +} + +$relativeChangedDartFiles = $changedDartFiles | ForEach-Object { $_ -replace '^apps/mobile/', '' } + +Push-Location $appDir +try { + if (-not $SkipPubGet) { + Invoke-Step -Name 'flutter pub get' -Executable 'flutter' -Arguments @('pub', 'get') + } + + if ($AllFiles) { + Invoke-Step -Name 'dart format .' -Executable 'dart' -Arguments @('format', '.') + } + elseif ($changedDartFiles.Count -gt 0) { + Invoke-Step -Name 'dart format changed files' -Executable 'dart' -Arguments (@('format') + $relativeChangedDartFiles) + } + else { + Write-Host 'No changed Dart files detected; skipping dart format. Use -AllFiles for a project-wide pass.' -ForegroundColor Yellow + } + + if ($ApplyProjectFixes) { + Invoke-Step -Name 'dart fix --apply' -Executable 'dart' -Arguments @('fix', '--apply') + } + else { + Invoke-Step -Name 'dart fix --dry-run' -Executable 'dart' -Arguments @('fix', '--dry-run') + } + + $analyzeArguments = @('analyze') + if (-not $StrictAnalyze) { + $analyzeArguments += @('--no-fatal-infos', '--no-fatal-warnings') + } + + if ($AllFiles) { + Invoke-Step -Name 'flutter analyze' -Executable 'flutter' -Arguments $analyzeArguments + } + elseif ($changedDartFiles.Count -gt 0) { + Invoke-Step -Name 'flutter analyze changed files' -Executable 'flutter' -Arguments ($analyzeArguments + $relativeChangedDartFiles) + } + else { + Write-Host 'No changed Dart files detected; skipping flutter analyze. Use -AllFiles for a project-wide pass.' -ForegroundColor Yellow + } + + if ($SkipRun) { + Write-Host 'Skipping flutter run because -SkipRun was provided.' -ForegroundColor Yellow + return + } + + $runArguments = @('run') + if ($DeviceId) { + $runArguments += @('-d', $DeviceId) + } + if ($FlutterRunArgs.Count -gt 0) { + $runArguments += $FlutterRunArgs + } + + Invoke-Step -Name 'flutter run' -Executable 'flutter' -Arguments $runArguments +} +finally { + Pop-Location +} diff --git a/tool/mobile-check-and-run.sh b/tool/mobile-check-and-run.sh new file mode 100644 index 0000000..20895f6 --- /dev/null +++ b/tool/mobile-check-and-run.sh @@ -0,0 +1,126 @@ +#!/usr/bin/env bash +set -euo pipefail + +DEVICE_ID="" +SKIP_PUB_GET=false +SKIP_RUN=false +STRICT_ANALYZE=false +APPLY_PROJECT_FIXES=false +ALL_FILES=false +RUN_ARGS=() + +while [[ $# -gt 0 ]]; do + case "$1" in + -d|--device) + DEVICE_ID="$2" + shift 2 + ;; + --skip-pub-get) + SKIP_PUB_GET=true + shift + ;; + --skip-run) + SKIP_RUN=true + shift + ;; + --strict-analyze) + STRICT_ANALYZE=true + shift + ;; + --apply-project-fixes) + APPLY_PROJECT_FIXES=true + shift + ;; + --all-files) + ALL_FILES=true + shift + ;; + --) + shift + RUN_ARGS=("$@") + break + ;; + *) + RUN_ARGS+=("$1") + shift + ;; + esac +done + +run_step() { + local name="$1" + shift + echo "==> $name" + "$@" +} + +map_changed_dart_files() { + git diff --name-only --diff-filter=ACMR -- ':(glob)apps/mobile/**/*.dart' + git ls-files --others --exclude-standard -- ':(glob)apps/mobile/**/*.dart' +} + +SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)" +REPO_ROOT="$(cd "$SCRIPT_DIR/.." && pwd)" +APP_DIR="$REPO_ROOT/apps/mobile" + +mapfile -t CHANGED_DART_FILES < <( + if [[ "$ALL_FILES" == true ]]; then + true + else + cd "$REPO_ROOT" + map_changed_dart_files | grep -E '^apps/mobile/.*\.dart$' | grep -Ev '\.(g|freezed)\.dart$' | sort -u || true + fi +) + +RELATIVE_CHANGED_DART_FILES=() +for file in "${CHANGED_DART_FILES[@]}"; do + RELATIVE_CHANGED_DART_FILES+=("${file#apps/mobile/}") +done + +cd "$APP_DIR" + +if [[ "$SKIP_PUB_GET" != true ]]; then + run_step "flutter pub get" flutter pub get +fi + +if [[ "$ALL_FILES" == true ]]; then + run_step "dart format ." dart format . +elif [[ ${#CHANGED_DART_FILES[@]} -gt 0 ]]; then + run_step "dart format changed files" dart format "${RELATIVE_CHANGED_DART_FILES[@]}" +else + echo "No changed Dart files detected; skipping dart format. Use --all-files for a project-wide pass." +fi + +if [[ "$APPLY_PROJECT_FIXES" == true ]]; then + run_step "dart fix --apply" dart fix --apply +else + run_step "dart fix --dry-run" dart fix --dry-run +fi + +ANALYZE_COMMAND=(flutter analyze) +if [[ "$STRICT_ANALYZE" != true ]]; then + ANALYZE_COMMAND+=(--no-fatal-infos --no-fatal-warnings) +fi + +if [[ "$ALL_FILES" == true ]]; then + run_step "flutter analyze" "${ANALYZE_COMMAND[@]}" +elif [[ ${#CHANGED_DART_FILES[@]} -gt 0 ]]; then + run_step "flutter analyze changed files" "${ANALYZE_COMMAND[@]}" "${RELATIVE_CHANGED_DART_FILES[@]}" +else + echo "No changed Dart files detected; skipping flutter analyze. Use --all-files for a project-wide pass." +fi + +if [[ "$SKIP_RUN" == true ]]; then + echo "Skipping flutter run because --skip-run was provided." + exit 0 +fi + +RUN_COMMAND=(flutter run) +if [[ -n "$DEVICE_ID" ]]; then + RUN_COMMAND+=(-d "$DEVICE_ID") +fi +if [[ ${#RUN_ARGS[@]} -gt 0 ]]; then + RUN_COMMAND+=("${RUN_ARGS[@]}") +fi + +run_step "flutter run" "${RUN_COMMAND[@]}" From d5af08d8361dd9eb8480c100d9791e85c99b9df2 Mon Sep 17 00:00:00 2001 From: MasuRii Date: Fri, 20 Mar 2026 10:23:37 +0800 Subject: [PATCH 06/22] chore(githooks): add pre-commit hook for format and check enforcement Add pre-commit hook that runs dart format, flutter analyze, prettier, typecheck, tests, and build for staged mobile and bridge source files. --- .githooks/pre-commit | 70 ++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 70 insertions(+) create mode 100644 .githooks/pre-commit diff --git a/.githooks/pre-commit b/.githooks/pre-commit new file mode 100644 index 0000000..7dde48b --- /dev/null +++ b/.githooks/pre-commit @@ -0,0 +1,70 @@ +#!/usr/bin/env bash +set -euo pipefail + +REPO_ROOT="$(git rev-parse --show-toplevel)" +cd "$REPO_ROOT" + +mapfile -t STAGED_DART_FILES < <( + git diff --cached --name-only --diff-filter=ACMR \ + | grep -E '^apps/mobile/.*\.dart$' \ + | grep -Ev '\.(g|freezed)\.dart$' \ + || true +) + +mapfile -t STAGED_BRIDGE_FILES < <( + git diff --cached --name-only --diff-filter=ACMR \ + | grep -E '^packages/bridge/' \ + | grep -Ev '^packages/bridge/(dist|node_modules)/' \ + | grep -E '\.(ts|js|cjs|mjs|json)$' \ + || true +) + +if [[ ${#STAGED_DART_FILES[@]} -eq 0 && ${#STAGED_BRIDGE_FILES[@]} -eq 0 ]]; then + echo "pre-commit: no staged mobile or bridge source files found; skipping checks." + exit 0 +fi + +if [[ ${#STAGED_DART_FILES[@]} -gt 0 ]]; then + echo "pre-commit: formatting staged Dart files" + dart format "${STAGED_DART_FILES[@]}" + git add "${STAGED_DART_FILES[@]}" + + ANALYZE_TARGETS=() + for file in "${STAGED_DART_FILES[@]}"; do + ANALYZE_TARGETS+=("${file#apps/mobile/}") + done + + echo "pre-commit: analyzing staged Dart files" + pushd apps/mobile > /dev/null + flutter analyze "${ANALYZE_TARGETS[@]}" + popd > /dev/null +fi + +if [[ ${#STAGED_BRIDGE_FILES[@]} -gt 0 ]]; then + if [[ ! -d packages/bridge/node_modules ]]; then + echo "pre-commit: packages/bridge/node_modules is missing. Run 'cd packages/bridge && npm ci' first." >&2 + exit 1 + fi + + BRIDGE_RELATIVE_FILES=() + for file in "${STAGED_BRIDGE_FILES[@]}"; do + BRIDGE_RELATIVE_FILES+=("${file#packages/bridge/}") + done + + echo "pre-commit: formatting staged bridge files" + pushd packages/bridge > /dev/null + npm exec prettier -- --write "${BRIDGE_RELATIVE_FILES[@]}" + popd > /dev/null + git add "${STAGED_BRIDGE_FILES[@]}" + + echo "pre-commit: typechecking bridge" + pushd packages/bridge > /dev/null + npm run typecheck + + echo "pre-commit: running bridge tests" + npm run test:ci + + echo "pre-commit: building bridge" + npm run build + popd > /dev/null +fi From 14f84a62c873494b43f06f7bae9c3bb3e144711d Mon Sep 17 00:00:00 2001 From: MasuRii Date: Fri, 20 Mar 2026 10:23:51 +0800 Subject: [PATCH 07/22] chore(bridge): add prettier for code formatting Add prettier configuration and npm scripts for format checking. Add prettier as dev dependency and configure print width, semicolons, quotes, and trailing commas. --- packages/bridge/.prettierignore | 3 +++ packages/bridge/.prettierrc.json | 6 ++++++ packages/bridge/package-lock.json | 23 +++++++++++++++------ packages/bridge/package.json | 33 ++++++++++++++++++------------- 4 files changed, 45 insertions(+), 20 deletions(-) create mode 100644 packages/bridge/.prettierignore create mode 100644 packages/bridge/.prettierrc.json diff --git a/packages/bridge/.prettierignore b/packages/bridge/.prettierignore new file mode 100644 index 0000000..2d0c064 --- /dev/null +++ b/packages/bridge/.prettierignore @@ -0,0 +1,3 @@ +dist/ +node_modules/ +coverage/ diff --git a/packages/bridge/.prettierrc.json b/packages/bridge/.prettierrc.json new file mode 100644 index 0000000..90abee2 --- /dev/null +++ b/packages/bridge/.prettierrc.json @@ -0,0 +1,6 @@ +{ + "printWidth": 100, + "semi": true, + "singleQuote": false, + "trailingComma": "all" +} diff --git a/packages/bridge/package-lock.json b/packages/bridge/package-lock.json index 747aed9..0df2e30 100644 --- a/packages/bridge/package-lock.json +++ b/packages/bridge/package-lock.json @@ -27,6 +27,7 @@ "@types/ws": "^8.5.13", "jest": "^29.7.0", "nodemon": "^3.1.7", + "prettier": "^3.8.1", "ts-jest": "^29.2.5", "ts-node": "^10.9.2", "typescript": "^5.6.0" @@ -1255,7 +1256,6 @@ "integrity": "sha512-F0R/h2+dsy5wJAUe3tAU6oqa2qbWY5TpNfL/RGmo1y38hiyO1w3x2jPtt76wmuaJI4DQnOBu21cNXQ2STIUUWg==", "dev": true, "license": "MIT", - "peer": true, "dependencies": { "undici-types": "~6.21.0" } @@ -1671,7 +1671,6 @@ } ], "license": "MIT", - "peer": true, "dependencies": { "baseline-browser-mapping": "^2.9.0", "caniuse-lite": "^1.0.30001759", @@ -3008,7 +3007,6 @@ "integrity": "sha512-NIy3oAFp9shda19hy4HK0HRTWKtPJmGdnvywu01nOqNC2vZg+Z+fvJDxpMQA88eb2I9EcafcdjYgsDthnYTvGw==", "dev": true, "license": "MIT", - "peer": true, "dependencies": { "@jest/core": "^29.7.0", "@jest/types": "^29.6.3", @@ -4315,6 +4313,22 @@ "node": ">=8" } }, + "node_modules/prettier": { + "version": "3.8.1", + "resolved": "https://registry.npmjs.org/prettier/-/prettier-3.8.1.tgz", + "integrity": "sha512-UOnG6LftzbdaHZcKoPFtOcCKztrQ57WkHDeRD9t/PTQtmT0NHSeWWepj6pS0z/N7+08BHFDQVUrfmfMRcZwbMg==", + "dev": true, + "license": "MIT", + "bin": { + "prettier": "bin/prettier.cjs" + }, + "engines": { + "node": ">=14" + }, + "funding": { + "url": "https://github.com/prettier/prettier?sponsor=1" + } + }, "node_modules/pretty-format": { "version": "29.7.0", "resolved": "https://registry.npmjs.org/pretty-format/-/pretty-format-29.7.0.tgz", @@ -5083,7 +5097,6 @@ "integrity": "sha512-f0FFpIdcHgn8zcPSbf1dRevwt047YMnaiJM3u2w2RewrB+fob/zePZcrOyQoLMMO7aBIddLcQIEK5dYjkLnGrQ==", "dev": true, "license": "MIT", - "peer": true, "dependencies": { "@cspotcode/source-map-support": "^0.8.0", "@tsconfig/node10": "^1.0.7", @@ -5164,7 +5177,6 @@ "integrity": "sha512-jl1vZzPDinLr9eUt3J/t7V6FgNEw9QjvBPdysz9KfQDD41fQrC2Y4vKQdiaUpFT4bXlb1RHhLpp8wtm6M5TgSw==", "dev": true, "license": "Apache-2.0", - "peer": true, "bin": { "tsc": "bin/tsc", "tsserver": "bin/tsserver" @@ -5461,7 +5473,6 @@ "resolved": "https://registry.npmjs.org/zod/-/zod-3.25.76.tgz", "integrity": "sha512-gzUt/qt81nXsFGKIFcC3YnfEAx5NkunCfnDlvuBSSFS02bcXu4Lmea0AFIUwbLWxWPx3d9p8S5QoaujKcNQxcQ==", "license": "MIT", - "peer": true, "funding": { "url": "https://github.com/sponsors/colinhacks" } diff --git a/packages/bridge/package.json b/packages/bridge/package.json index 81d14ce..bdf1304 100644 --- a/packages/bridge/package.json +++ b/packages/bridge/package.json @@ -7,32 +7,37 @@ "main": "dist/index.js", "scripts": { "build": "tsc -p tsconfig.json", - "typecheck": "tsc -p tsconfig.json --noEmit", + "check": "npm run format:check && npm run typecheck && npm run test:ci && npm run build", "dev": "nodemon --exec ts-node src/index.ts", + "format": "prettier --write .", + "format:check": "prettier --check .", "start": "node dist/index.js", - "test": "jest" + "test": "jest", + "test:ci": "jest --passWithNoTests --runInBand", + "typecheck": "tsc -p tsconfig.json --noEmit" }, "dependencies": { - "express": "^4.21.1", - "ws": "^8.18.0", "@anthropic-ai/sdk": "^0.79.0", + "cors": "^2.8.5", "dotenv": "^16.4.7", - "zod": "^3.23.8", - "uuid": "^10.0.0", + "express": "^4.21.1", "simple-git": "^3.27.0", - "cors": "^2.8.5" + "uuid": "^10.0.0", + "ws": "^8.18.0", + "zod": "^3.23.8" }, "devDependencies": { - "typescript": "^5.6.0", + "@types/cors": "^2.8.17", "@types/express": "^5.0.0", - "@types/ws": "^8.5.13", + "@types/jest": "^29.5.14", "@types/node": "^22.0.0", "@types/uuid": "^10.0.0", - "@types/cors": "^2.8.17", - "ts-node": "^10.9.2", - "nodemon": "^3.1.7", + "@types/ws": "^8.5.13", "jest": "^29.7.0", - "@types/jest": "^29.5.14", - "ts-jest": "^29.2.5" + "nodemon": "^3.1.7", + "prettier": "^3.8.1", + "ts-jest": "^29.2.5", + "ts-node": "^10.9.2", + "typescript": "^5.6.0" } } From 09e64b41288df1f14fd6b64990ec253be56a2428 Mon Sep 17 00:00:00 2001 From: MasuRii Date: Fri, 20 Mar 2026 10:24:06 +0800 Subject: [PATCH 08/22] style(bridge): apply prettier formatting to source files Apply consistent formatting across all TypeScript source files with trailing commas, collapsed function signatures, and aligned object properties. --- .../bridge/src/agents/agent_sdk_adapter.ts | 28 ++---- packages/bridge/src/agents/session_manager.ts | 30 ++++--- packages/bridge/src/agents/tool_executor.ts | 89 ++++++++++++------- packages/bridge/src/auth/rate_limiter.ts | 6 +- packages/bridge/src/auth/token_validator.ts | 12 +-- packages/bridge/src/config.ts | 4 +- packages/bridge/src/files/file_service.ts | 8 +- packages/bridge/src/git/diff_parser.ts | 5 +- packages/bridge/src/git/git_service.ts | 7 +- packages/bridge/src/hooks/receiver.ts | 2 +- .../bridge/src/notifications/event_bus.ts | 9 +- packages/bridge/src/server.ts | 2 +- packages/bridge/src/types.ts | 9 +- .../src/websocket/connection_manager.ts | 5 +- .../bridge/src/websocket/message_handler.ts | 41 ++++----- packages/bridge/src/websocket/server.ts | 2 +- 16 files changed, 114 insertions(+), 145 deletions(-) diff --git a/packages/bridge/src/agents/agent_sdk_adapter.ts b/packages/bridge/src/agents/agent_sdk_adapter.ts index 4dd8e81..7eb9018 100644 --- a/packages/bridge/src/agents/agent_sdk_adapter.ts +++ b/packages/bridge/src/agents/agent_sdk_adapter.ts @@ -23,18 +23,12 @@ export class AgentSdkAdapter { private sessionManager: AgentSessionManager; private connectionManager: ConnectionManager; - constructor( - sessionManager: AgentSessionManager, - connectionManager: ConnectionManager - ) { + constructor(sessionManager: AgentSessionManager, connectionManager: ConnectionManager) { this.sessionManager = sessionManager; this.connectionManager = connectionManager; } - async handleSessionStart( - payload: SessionStartPayload, - clientId: string - ): Promise { + async handleSessionStart(payload: SessionStartPayload, clientId: string): Promise { try { const sessionId = await this.sessionManager.createSession({ sessionId: payload.session_id, @@ -75,16 +69,9 @@ export class AgentSdkAdapter { } } - async handleMessage( - payload: MessagePayload, - clientId: string - ): Promise { + async handleMessage(payload: MessagePayload, clientId: string): Promise { try { - await this.sessionManager.sendMessage( - payload.session_id, - payload.content, - clientId - ); + await this.sessionManager.sendMessage(payload.session_id, payload.content, clientId); } catch (err) { log(`Failed to send message: ${String(err)}`); const errorMsg: BridgeMessage = { @@ -101,15 +88,12 @@ export class AgentSdkAdapter { } } - async handleApprovalResponse( - payload: ApprovalResponsePayload, - clientId: string - ): Promise { + async handleApprovalResponse(payload: ApprovalResponsePayload, clientId: string): Promise { try { await this.sessionManager.executeToolCall( payload.session_id, payload.tool_call_id, - payload.decision + payload.decision, ); } catch (err) { log(`Failed to handle approval response: ${String(err)}`); diff --git a/packages/bridge/src/agents/session_manager.ts b/packages/bridge/src/agents/session_manager.ts index abed79f..0dbd510 100644 --- a/packages/bridge/src/agents/session_manager.ts +++ b/packages/bridge/src/agents/session_manager.ts @@ -80,11 +80,7 @@ export class AgentSessionManager { }); } - async sendMessage( - sessionId: string, - content: string, - clientId: string - ): Promise { + async sendMessage(sessionId: string, content: string, clientId: string): Promise { const session = this.sessions.get(sessionId); if (!session) throw new Error(`Session not found: ${sessionId}`); @@ -97,7 +93,11 @@ export class AgentSessionManager { session_id: sessionId, message_id: messageId, }; - eventBus.emitTyped("session-event", { type: "stream_start", ...startPayload, client_id: clientId }); + eventBus.emitTyped("session-event", { + type: "stream_start", + ...startPayload, + client_id: clientId, + }); try { const streamParams: Anthropic.MessageStreamParams = { @@ -147,7 +147,11 @@ export class AgentSessionManager { tool_input: block.input as Record, message: `Tool call requested: ${block.name}`, }; - eventBus.emitTyped("tool-event", { type: "approval_required", ...approvalPayload, client_id: clientId }); + eventBus.emitTyped("tool-event", { + type: "approval_required", + ...approvalPayload, + client_id: clientId, + }); } } else if (event.type === "message_delta") { if (event.delta.stop_reason) { @@ -166,7 +170,11 @@ export class AgentSessionManager { message_id: messageId, stop_reason: stopReason, }; - eventBus.emitTyped("session-event", { type: "stream_end", ...endPayload, client_id: clientId }); + eventBus.emitTyped("session-event", { + type: "stream_end", + ...endPayload, + client_id: clientId, + }); } catch (err) { session.meta.status = "idle"; log(`Stream error in session ${sessionId}: ${String(err)}`); @@ -174,11 +182,7 @@ export class AgentSessionManager { } } - async executeToolCall( - sessionId: string, - toolCallId: string, - decision: string - ): Promise { + async executeToolCall(sessionId: string, toolCallId: string, decision: string): Promise { const session = this.sessions.get(sessionId); if (!session) throw new Error(`Session not found: ${sessionId}`); diff --git a/packages/bridge/src/agents/tool_executor.ts b/packages/bridge/src/agents/tool_executor.ts index db2a45f..9c23d9b 100644 --- a/packages/bridge/src/agents/tool_executor.ts +++ b/packages/bridge/src/agents/tool_executor.ts @@ -33,7 +33,7 @@ export class ToolExecutor { async execute( tool: string, params: Record, - workingDir: string + workingDir: string, ): Promise { const start = Date.now(); @@ -89,13 +89,18 @@ export class ToolExecutor { private async readFile( params: Record, workingDir: string, - start: number + start: number, ): Promise { const filePath = String(params["path"] ?? ""); const resolved = resolveWithinRoot(filePath, workingDir); if (!isWithinAllowedRoot(resolved)) { - return { success: false, content: "", error: "Path outside allowed root", durationMs: Date.now() - start }; + return { + success: false, + content: "", + error: "Path outside allowed root", + durationMs: Date.now() - start, + }; } const content = await readFileAsync(resolved, "utf8"); @@ -105,7 +110,7 @@ export class ToolExecutor { private async editFile( params: Record, workingDir: string, - start: number + start: number, ): Promise { const filePath = String(params["path"] ?? ""); const oldStr = String(params["old_string"] ?? ""); @@ -113,12 +118,22 @@ export class ToolExecutor { const resolved = resolveWithinRoot(filePath, workingDir); if (!isWithinAllowedRoot(resolved)) { - return { success: false, content: "", error: "Path outside allowed root", durationMs: Date.now() - start }; + return { + success: false, + content: "", + error: "Path outside allowed root", + durationMs: Date.now() - start, + }; } const original = await readFileAsync(resolved, "utf8"); if (!original.includes(oldStr)) { - return { success: false, content: "", error: "old_string not found in file", durationMs: Date.now() - start }; + return { + success: false, + content: "", + error: "old_string not found in file", + durationMs: Date.now() - start, + }; } const updated = original.replace(oldStr, newStr); @@ -129,7 +144,7 @@ export class ToolExecutor { private bashCommand( params: Record, workingDir: string, - start: number + start: number, ): Promise { return new Promise((resolve) => { const command = String(params["command"] ?? ""); @@ -155,8 +170,12 @@ export class ToolExecutor { let stdout = ""; let stderr = ""; - child.stdout.on("data", (d: Buffer) => { stdout += d.toString(); }); - child.stderr.on("data", (d: Buffer) => { stderr += d.toString(); }); + child.stdout.on("data", (d: Buffer) => { + stdout += d.toString(); + }); + child.stderr.on("data", (d: Buffer) => { + stderr += d.toString(); + }); child.on("close", (code) => { const success = code === 0; @@ -182,16 +201,18 @@ export class ToolExecutor { private async glob( params: Record, workingDir: string, - start: number + start: number, ): Promise { const pattern = String(params["pattern"] ?? "**/*"); - const baseDir = resolveWithinRoot( - String(params["base_dir"] ?? "."), - workingDir - ); + const baseDir = resolveWithinRoot(String(params["base_dir"] ?? "."), workingDir); if (!isWithinAllowedRoot(baseDir)) { - return { success: false, content: "", error: "Path outside allowed root", durationMs: Date.now() - start }; + return { + success: false, + content: "", + error: "Path outside allowed root", + durationMs: Date.now() - start, + }; } // Use native fs walk for glob @@ -204,7 +225,7 @@ export class ToolExecutor { base: string, current: string, pattern: string, - results: string[] + results: string[], ): Promise { let entries: string[]; try { @@ -248,16 +269,18 @@ export class ToolExecutor { private async grep( params: Record, workingDir: string, - start: number + start: number, ): Promise { const searchPattern = String(params["pattern"] ?? ""); - const searchPath = resolveWithinRoot( - String(params["path"] ?? "."), - workingDir - ); + const searchPath = resolveWithinRoot(String(params["path"] ?? "."), workingDir); if (!isWithinAllowedRoot(searchPath)) { - return { success: false, content: "", error: "Path outside allowed root", durationMs: Date.now() - start }; + return { + success: false, + content: "", + error: "Path outside allowed root", + durationMs: Date.now() - start, + }; } const results: string[] = []; @@ -268,7 +291,7 @@ export class ToolExecutor { private async grepDirectory( searchPath: string, pattern: string, - results: string[] + results: string[], ): Promise { let stat; try { @@ -295,11 +318,7 @@ export class ToolExecutor { } } - private async grepFile( - filePath: string, - pattern: string, - results: string[] - ): Promise { + private async grepFile(filePath: string, pattern: string, results: string[]): Promise { let content: string; try { content = await readFileAsync(filePath, "utf8"); @@ -320,15 +339,17 @@ export class ToolExecutor { private async listFiles( params: Record, workingDir: string, - start: number + start: number, ): Promise { - const dirPath = resolveWithinRoot( - String(params["path"] ?? "."), - workingDir - ); + const dirPath = resolveWithinRoot(String(params["path"] ?? "."), workingDir); if (!isWithinAllowedRoot(dirPath)) { - return { success: false, content: "", error: "Path outside allowed root", durationMs: Date.now() - start }; + return { + success: false, + content: "", + error: "Path outside allowed root", + durationMs: Date.now() - start, + }; } const entries = await readdirAsync(dirPath); diff --git a/packages/bridge/src/auth/rate_limiter.ts b/packages/bridge/src/auth/rate_limiter.ts index 8f61a7d..2416e45 100644 --- a/packages/bridge/src/auth/rate_limiter.ts +++ b/packages/bridge/src/auth/rate_limiter.ts @@ -18,11 +18,7 @@ function getClientIp(req: Request): string { return req.socket.remoteAddress ?? "unknown"; } -export function rateLimiter( - req: Request, - res: Response, - next: NextFunction -): void { +export function rateLimiter(req: Request, res: Response, next: NextFunction): void { const ip = getClientIp(req); const now = Date.now(); diff --git a/packages/bridge/src/auth/token_validator.ts b/packages/bridge/src/auth/token_validator.ts index 646b37b..1791e9a 100644 --- a/packages/bridge/src/auth/token_validator.ts +++ b/packages/bridge/src/auth/token_validator.ts @@ -9,11 +9,7 @@ function extractBearerToken(req: Request): string | null { return auth.slice(7); } -export function validateBridgeToken( - req: Request, - res: Response, - next: NextFunction -): void { +export function validateBridgeToken(req: Request, res: Response, next: NextFunction): void { const token = extractBearerToken(req); if (!token || token !== config.BRIDGE_TOKEN) { res.status(401).json({ error: "Unauthorized", message: "Invalid or missing bridge token" }); @@ -22,11 +18,7 @@ export function validateBridgeToken( next(); } -export function validateHookToken( - req: Request, - res: Response, - next: NextFunction -): void { +export function validateHookToken(req: Request, res: Response, next: NextFunction): void { const token = extractBearerToken(req); if (!token || token !== config.HOOK_TOKEN) { res.status(401).json({ error: "Unauthorized", message: "Invalid or missing hook token" }); diff --git a/packages/bridge/src/config.ts b/packages/bridge/src/config.ts index d07d58d..2c04b30 100644 --- a/packages/bridge/src/config.ts +++ b/packages/bridge/src/config.ts @@ -9,9 +9,7 @@ const configSchema = z.object({ HOOK_TOKEN: z.string().min(1, "HOOK_TOKEN is required"), ANTHROPIC_API_KEY: z.string().min(1, "ANTHROPIC_API_KEY is required"), AGENT_MODEL: z.string().default("claude-opus-4-6"), - ALLOWED_PROJECT_ROOT: z - .string() - .min(1, "ALLOWED_PROJECT_ROOT is required"), + ALLOWED_PROJECT_ROOT: z.string().min(1, "ALLOWED_PROJECT_ROOT is required"), }); function loadConfig() { diff --git a/packages/bridge/src/files/file_service.ts b/packages/bridge/src/files/file_service.ts index 9d0027c..8b3ffe9 100644 --- a/packages/bridge/src/files/file_service.ts +++ b/packages/bridge/src/files/file_service.ts @@ -41,7 +41,7 @@ export class FileService { offset?: number; limit?: number; includeHidden?: boolean; - } = {} + } = {}, ): Promise { const resolved = path.resolve(dirPath); this.validatePath(resolved); @@ -94,7 +94,7 @@ export class FileService { options: { offset?: number; limit?: number; - } = {} + } = {}, ): Promise { const resolved = path.resolve(filePath); this.validatePath(resolved); @@ -119,9 +119,7 @@ export class FileService { private validatePath(p: string): void { const resolvedRoot = path.resolve(this.allowedRoot); if (!p.startsWith(resolvedRoot + path.sep) && p !== resolvedRoot) { - throw new Error( - `Access denied: path "${p}" is outside the allowed root "${resolvedRoot}"` - ); + throw new Error(`Access denied: path "${p}" is outside the allowed root "${resolvedRoot}"`); } } } diff --git a/packages/bridge/src/git/diff_parser.ts b/packages/bridge/src/git/diff_parser.ts index 7ac075f..922b24f 100644 --- a/packages/bridge/src/git/diff_parser.ts +++ b/packages/bridge/src/git/diff_parser.ts @@ -95,10 +95,7 @@ export function parseDiff(rawDiff: string): DiffFile[] { while (i < lines.length) { const dl = lines[i]; - if ( - FILE_HEADER_RE.test(dl) || - HUNK_HEADER_RE.test(dl) - ) { + if (FILE_HEADER_RE.test(dl) || HUNK_HEADER_RE.test(dl)) { break; } diff --git a/packages/bridge/src/git/git_service.ts b/packages/bridge/src/git/git_service.ts index 4d05a6e..5941f7f 100644 --- a/packages/bridge/src/git/git_service.ts +++ b/packages/bridge/src/git/git_service.ts @@ -1,11 +1,6 @@ import simpleGit, { type SimpleGit, type StatusResult } from "simple-git"; import { parseDiff } from "./diff_parser"; -import type { - GitStatusPayload, - GitFileChange, - DiffFile, - GitBranch, -} from "../types"; +import type { GitStatusPayload, GitFileChange, DiffFile, GitBranch } from "../types"; function log(msg: string): void { console.log(`[${new Date().toISOString()}] [GitService] ${msg}`); diff --git a/packages/bridge/src/hooks/receiver.ts b/packages/bridge/src/hooks/receiver.ts index 9cca572..e4e4766 100644 --- a/packages/bridge/src/hooks/receiver.ts +++ b/packages/bridge/src/hooks/receiver.ts @@ -13,7 +13,7 @@ function log(msg: string): void { export function createHooksRouter( eventQueue: EventQueue, - connectionManager: ConnectionManager + connectionManager: ConnectionManager, ): Router { const router = Router(); diff --git a/packages/bridge/src/notifications/event_bus.ts b/packages/bridge/src/notifications/event_bus.ts index 457d67b..7bd6d18 100644 --- a/packages/bridge/src/notifications/event_bus.ts +++ b/packages/bridge/src/notifications/event_bus.ts @@ -8,23 +8,20 @@ export type EventBusEvents = { }; class TypedEventBus extends EventEmitter { - emitTyped( - event: K, - ...args: EventBusEvents[K] - ): boolean { + emitTyped(event: K, ...args: EventBusEvents[K]): boolean { return this.emit(event, ...args); } onTyped( event: K, - listener: (...args: EventBusEvents[K]) => void + listener: (...args: EventBusEvents[K]) => void, ): this { return this.on(event, listener as (...args: unknown[]) => void); } offTyped( event: K, - listener: (...args: EventBusEvents[K]) => void + listener: (...args: EventBusEvents[K]) => void, ): this { return this.off(event, listener as (...args: unknown[]) => void); } diff --git a/packages/bridge/src/server.ts b/packages/bridge/src/server.ts index 956c4b6..12e5903 100644 --- a/packages/bridge/src/server.ts +++ b/packages/bridge/src/server.ts @@ -32,7 +32,7 @@ export async function startServer(): Promise { connectionManager, agentSdkAdapter, agentSessionManager, - gitService + gitService, ); // Express app diff --git a/packages/bridge/src/types.ts b/packages/bridge/src/types.ts index 672b909..253f201 100644 --- a/packages/bridge/src/types.ts +++ b/packages/bridge/src/types.ts @@ -137,14 +137,7 @@ export interface ClaudeEventPayload { export interface GitFileChange { path: string; - status: - | "added" - | "modified" - | "deleted" - | "renamed" - | "copied" - | "untracked" - | "unknown"; + status: "added" | "modified" | "deleted" | "renamed" | "copied" | "untracked" | "unknown"; staged: boolean; } diff --git a/packages/bridge/src/websocket/connection_manager.ts b/packages/bridge/src/websocket/connection_manager.ts index 8f52290..94f0b84 100644 --- a/packages/bridge/src/websocket/connection_manager.ts +++ b/packages/bridge/src/websocket/connection_manager.ts @@ -36,10 +36,7 @@ export class ConnectionManager { return this.clients.get(id); } - broadcast( - message: BridgeMessage, - filter?: (client: MobileClient) => boolean - ): void { + broadcast(message: BridgeMessage, filter?: (client: MobileClient) => boolean): void { const json = JSON.stringify(message); for (const client of this.clients.values()) { if (!client.authenticated) continue; diff --git a/packages/bridge/src/websocket/message_handler.ts b/packages/bridge/src/websocket/message_handler.ts index 122ca6b..10b05b5 100644 --- a/packages/bridge/src/websocket/message_handler.ts +++ b/packages/bridge/src/websocket/message_handler.ts @@ -36,7 +36,7 @@ function ts(): string { function errorMsg( code: string, message: string, - requestType?: string + requestType?: string, ): BridgeMessage { return { type: "error", @@ -53,7 +53,7 @@ export class MessageHandler { private connectionManager: ConnectionManager, private agentSdkAdapter: AgentSdkAdapter, private agentSessionManager: AgentSessionManager, - private gitService: GitService + private gitService: GitService, ) { this.fileService = new FileService(config.ALLOWED_PROJECT_ROOT); } @@ -66,7 +66,7 @@ export class MessageHandler { } catch { this.connectionManager.sendToClient( clientId, - errorMsg("PARSE_ERROR", "Invalid JSON message") + errorMsg("PARSE_ERROR", "Invalid JSON message"), ); return; } @@ -88,18 +88,15 @@ export class MessageHandler { // All other messages require authentication const client = this.connectionManager.getClient(clientId); if (!client || !client.authenticated) { - this.connectionManager.sendToClient( - clientId, - { - type: "connection_error", - id: uuidv4(), - timestamp: ts(), - payload: { - code: "NOT_AUTHENTICATED", - message: "Client must authenticate before sending messages", - } as ConnectionErrorPayload, - } - ); + this.connectionManager.sendToClient(clientId, { + type: "connection_error", + id: uuidv4(), + timestamp: ts(), + payload: { + code: "NOT_AUTHENTICATED", + message: "Client must authenticate before sending messages", + } as ConnectionErrorPayload, + }); return; } @@ -114,7 +111,10 @@ export class MessageHandler { break; case "approval_response": - await this.agentSdkAdapter.handleApprovalResponse(payload as ApprovalResponsePayload, clientId); + await this.agentSdkAdapter.handleApprovalResponse( + payload as ApprovalResponsePayload, + clientId, + ); break; case "session_end": @@ -149,15 +149,12 @@ export class MessageHandler { log(`Unknown message type: ${type} from client ${clientId}`); this.connectionManager.sendToClient( clientId, - errorMsg("UNKNOWN_TYPE", `Unknown message type: ${type}`, type) + errorMsg("UNKNOWN_TYPE", `Unknown message type: ${type}`, type), ); } } catch (err) { log(`Error handling ${type} for client ${clientId}: ${String(err)}`); - this.connectionManager.sendToClient( - clientId, - errorMsg("HANDLER_ERROR", String(err), type) - ); + this.connectionManager.sendToClient(clientId, errorMsg("HANDLER_ERROR", String(err), type)); } } @@ -226,7 +223,7 @@ export class MessageHandler { private async handleGitDiff( clientId: string, payload: GitDiffPayload, - requestId?: string + requestId?: string, ): Promise { const files = await this.gitService.getDiff(payload.files, payload.cached); this.connectionManager.sendToClient(clientId, { diff --git a/packages/bridge/src/websocket/server.ts b/packages/bridge/src/websocket/server.ts index 32addd6..c9ed12e 100644 --- a/packages/bridge/src/websocket/server.ts +++ b/packages/bridge/src/websocket/server.ts @@ -17,7 +17,7 @@ export class WebSocketServer { constructor( httpServer: Server, private connectionManager: ConnectionManager, - private messageHandler: MessageHandler + private messageHandler: MessageHandler, ) { this.wss = new WsServer({ server: httpServer, From 791d81cb698287d961a10f788d448b323151de32 Mon Sep 17 00:00:00 2001 From: MasuRii Date: Fri, 20 Mar 2026 10:24:17 +0800 Subject: [PATCH 09/22] chore(mobile): configure analyzer lints and pre-build checks Add analysis options with linter rules for return types, const preferences, and code organization. Configure Android build to run flutter analyze before preBuild. --- apps/mobile/analysis_options.yaml | 17 +++++++++++++- apps/mobile/android/app/build.gradle.kts | 30 ++++++++++++++++++++++++ 2 files changed, 46 insertions(+), 1 deletion(-) diff --git a/apps/mobile/analysis_options.yaml b/apps/mobile/analysis_options.yaml index 388cd92..7e160a5 100644 --- a/apps/mobile/analysis_options.yaml +++ b/apps/mobile/analysis_options.yaml @@ -1,3 +1,18 @@ include: package:flutter_lints/flutter.yaml -# Scaffold-only: customize analysis/lints as the app is implemented. +analyzer: + exclude: + - '**/*.g.dart' + - '**/*.freezed.dart' + +linter: + rules: + always_declare_return_types: true + avoid_print: true + directives_ordering: true + prefer_const_constructors: true + prefer_const_declarations: true + prefer_final_fields: true + prefer_final_locals: true + sort_child_properties_last: true + unawaited_futures: true diff --git a/apps/mobile/android/app/build.gradle.kts b/apps/mobile/android/app/build.gradle.kts index 9781900..3eee2d7 100644 --- a/apps/mobile/android/app/build.gradle.kts +++ b/apps/mobile/android/app/build.gradle.kts @@ -1,3 +1,5 @@ +import java.util.Properties + plugins { id("com.android.application") id("kotlin-android") @@ -5,6 +7,34 @@ plugins { id("dev.flutter.flutter-gradle-plugin") } +val localProperties = Properties().apply { + val localPropertiesFile = rootProject.file("local.properties") + if (localPropertiesFile.exists()) { + localPropertiesFile.inputStream().use(::load) + } +} + +val isWindows = System.getProperty("os.name").contains("Windows", ignoreCase = true) +val flutterSdk = localProperties.getProperty("flutter.sdk") ?: System.getenv("FLUTTER_ROOT") +val flutterExecutable = when { + !flutterSdk.isNullOrBlank() && isWindows -> "$flutterSdk\\bin\\flutter.bat" + !flutterSdk.isNullOrBlank() -> "$flutterSdk/bin/flutter" + isWindows -> "flutter.bat" + else -> "flutter" +} +val flutterProjectDir = rootProject.projectDir.parentFile + +val analyzeFlutterBeforeBuild = tasks.register("analyzeFlutterBeforeBuild") { + group = "verification" + description = "Runs flutter analyze before Android builds." + workingDir = flutterProjectDir + commandLine(flutterExecutable, "analyze", "--no-fatal-infos", "--no-fatal-warnings") +} + +tasks.named("preBuild") { + dependsOn(analyzeFlutterBeforeBuild) +} + android { namespace = "com.example.recursor_mobile" compileSdk = flutter.compileSdkVersion From a81fbc7f9d5e21bb913aa008f899643636b74b2d Mon Sep 17 00:00:00 2001 From: MasuRii Date: Fri, 20 Mar 2026 10:24:21 +0800 Subject: [PATCH 10/22] test(mobile): update widget test to placeholder shell Replace counter smoke test with minimal placeholder test that renders a MaterialApp scaffold for the ReCursor shell. --- apps/mobile/test/widget_test.dart | 35 +++++++++++-------------------- 1 file changed, 12 insertions(+), 23 deletions(-) diff --git a/apps/mobile/test/widget_test.dart b/apps/mobile/test/widget_test.dart index 296fe28..f0bf8e2 100644 --- a/apps/mobile/test/widget_test.dart +++ b/apps/mobile/test/widget_test.dart @@ -1,30 +1,19 @@ -// This is a basic Flutter widget test. -// -// To perform an interaction with a widget in your test, use the WidgetTester -// utility in the flutter_test package. For example, you can send tap and scroll -// gestures. You can also use WidgetTester to find child widgets in the widget -// tree, read text, and verify that the values of widget properties are correct. - import 'package:flutter/material.dart'; import 'package:flutter_test/flutter_test.dart'; -import 'package:recursor_mobile/main.dart'; - void main() { - testWidgets('Counter increments smoke test', (WidgetTester tester) async { - // Build our app and trigger a frame. - await tester.pumpWidget(const MyApp()); - - // Verify that our counter starts at 0. - expect(find.text('0'), findsOneWidget); - expect(find.text('1'), findsNothing); - - // Tap the '+' icon and trigger a frame. - await tester.tap(find.byIcon(Icons.add)); - await tester.pump(); + testWidgets('renders ReCursor placeholder shell', + (WidgetTester tester) async { + await tester.pumpWidget( + const MaterialApp( + home: Scaffold( + body: Center( + child: Text('ReCursor'), + ), + ), + ), + ); - // Verify that our counter has incremented. - expect(find.text('0'), findsNothing); - expect(find.text('1'), findsOneWidget); + expect(find.text('ReCursor'), findsOneWidget); }); } From 18d9b3b5a9800f8a8598267f33e225ce23499c26 Mon Sep 17 00:00:00 2001 From: MasuRii Date: Fri, 20 Mar 2026 10:24:38 +0800 Subject: [PATCH 11/22] build(mobile): update generated plugin registrants for new dependencies Add plugin registrations for flutter_local_notifications, flutter_secure_storage, integration_test, mobile_scanner, and package_info_plus in Android and iOS generated files. --- .../plugins/GeneratedPluginRegistrant.java | 55 ++++++++++++++++ .../ios/Runner/GeneratedPluginRegistrant.m | 63 +++++++++++++++++++ 2 files changed, 118 insertions(+) diff --git a/apps/mobile/android/app/src/main/java/io/flutter/plugins/GeneratedPluginRegistrant.java b/apps/mobile/android/app/src/main/java/io/flutter/plugins/GeneratedPluginRegistrant.java index 539ab02..fc67028 100644 --- a/apps/mobile/android/app/src/main/java/io/flutter/plugins/GeneratedPluginRegistrant.java +++ b/apps/mobile/android/app/src/main/java/io/flutter/plugins/GeneratedPluginRegistrant.java @@ -15,5 +15,60 @@ public final class GeneratedPluginRegistrant { private static final String TAG = "GeneratedPluginRegistrant"; public static void registerWith(@NonNull FlutterEngine flutterEngine) { + try { + flutterEngine.getPlugins().add(new com.dexterous.flutterlocalnotifications.FlutterLocalNotificationsPlugin()); + } catch (Exception e) { + Log.e(TAG, "Error registering plugin flutter_local_notifications, com.dexterous.flutterlocalnotifications.FlutterLocalNotificationsPlugin", e); + } + try { + flutterEngine.getPlugins().add(new com.it_nomads.fluttersecurestorage.FlutterSecureStoragePlugin()); + } catch (Exception e) { + Log.e(TAG, "Error registering plugin flutter_secure_storage, com.it_nomads.fluttersecurestorage.FlutterSecureStoragePlugin", e); + } + try { + flutterEngine.getPlugins().add(new dev.flutter.plugins.integration_test.IntegrationTestPlugin()); + } catch (Exception e) { + Log.e(TAG, "Error registering plugin integration_test, dev.flutter.plugins.integration_test.IntegrationTestPlugin", e); + } + try { + flutterEngine.getPlugins().add(new com.github.dart_lang.jni.JniPlugin()); + } catch (Exception e) { + Log.e(TAG, "Error registering plugin jni, com.github.dart_lang.jni.JniPlugin", e); + } + try { + flutterEngine.getPlugins().add(new dev.steenbakker.mobile_scanner.MobileScannerPlugin()); + } catch (Exception e) { + Log.e(TAG, "Error registering plugin mobile_scanner, dev.steenbakker.mobile_scanner.MobileScannerPlugin", e); + } + try { + flutterEngine.getPlugins().add(new dev.fluttercommunity.plus.packageinfo.PackageInfoPlugin()); + } catch (Exception e) { + Log.e(TAG, "Error registering plugin package_info_plus, dev.fluttercommunity.plus.packageinfo.PackageInfoPlugin", e); + } + try { + flutterEngine.getPlugins().add(new io.flutter.plugins.pathprovider.PathProviderPlugin()); + } catch (Exception e) { + Log.e(TAG, "Error registering plugin path_provider_android, io.flutter.plugins.pathprovider.PathProviderPlugin", e); + } + try { + flutterEngine.getPlugins().add(new pl.leancode.patrol.PatrolPlugin()); + } catch (Exception e) { + Log.e(TAG, "Error registering plugin patrol, pl.leancode.patrol.PatrolPlugin", e); + } + try { + flutterEngine.getPlugins().add(new io.sentry.flutter.SentryFlutterPlugin()); + } catch (Exception e) { + Log.e(TAG, "Error registering plugin sentry_flutter, io.sentry.flutter.SentryFlutterPlugin", e); + } + try { + flutterEngine.getPlugins().add(new com.csdcorp.speech_to_text.SpeechToTextPlugin()); + } catch (Exception e) { + Log.e(TAG, "Error registering plugin speech_to_text, com.csdcorp.speech_to_text.SpeechToTextPlugin", e); + } + try { + flutterEngine.getPlugins().add(new eu.simonbinder.sqlite3_flutter_libs.Sqlite3FlutterLibsPlugin()); + } catch (Exception e) { + Log.e(TAG, "Error registering plugin sqlite3_flutter_libs, eu.simonbinder.sqlite3_flutter_libs.Sqlite3FlutterLibsPlugin", e); + } } } diff --git a/apps/mobile/ios/Runner/GeneratedPluginRegistrant.m b/apps/mobile/ios/Runner/GeneratedPluginRegistrant.m index efe65ec..1d16b8f 100644 --- a/apps/mobile/ios/Runner/GeneratedPluginRegistrant.m +++ b/apps/mobile/ios/Runner/GeneratedPluginRegistrant.m @@ -6,9 +6,72 @@ #import "GeneratedPluginRegistrant.h" +#if __has_include() +#import +#else +@import flutter_local_notifications; +#endif + +#if __has_include() +#import +#else +@import flutter_secure_storage; +#endif + +#if __has_include() +#import +#else +@import integration_test; +#endif + +#if __has_include() +#import +#else +@import mobile_scanner; +#endif + +#if __has_include() +#import +#else +@import package_info_plus; +#endif + +#if __has_include() +#import +#else +@import patrol; +#endif + +#if __has_include() +#import +#else +@import sentry_flutter; +#endif + +#if __has_include() +#import +#else +@import speech_to_text; +#endif + +#if __has_include() +#import +#else +@import sqlite3_flutter_libs; +#endif + @implementation GeneratedPluginRegistrant + (void)registerWithRegistry:(NSObject*)registry { + [FlutterLocalNotificationsPlugin registerWithRegistrar:[registry registrarForPlugin:@"FlutterLocalNotificationsPlugin"]]; + [FlutterSecureStoragePlugin registerWithRegistrar:[registry registrarForPlugin:@"FlutterSecureStoragePlugin"]]; + [IntegrationTestPlugin registerWithRegistrar:[registry registrarForPlugin:@"IntegrationTestPlugin"]]; + [MobileScannerPlugin registerWithRegistrar:[registry registrarForPlugin:@"MobileScannerPlugin"]]; + [FPPPackageInfoPlusPlugin registerWithRegistrar:[registry registrarForPlugin:@"FPPPackageInfoPlusPlugin"]]; + [PatrolPlugin registerWithRegistrar:[registry registrarForPlugin:@"PatrolPlugin"]]; + [SentryFlutterPlugin registerWithRegistrar:[registry registrarForPlugin:@"SentryFlutterPlugin"]]; + [SpeechToTextPlugin registerWithRegistrar:[registry registrarForPlugin:@"SpeechToTextPlugin"]]; + [Sqlite3FlutterLibsPlugin registerWithRegistrar:[registry registrarForPlugin:@"Sqlite3FlutterLibsPlugin"]]; } @end From 3a81b296a3530d2d025e30a6d0eefcf1c761a10e Mon Sep 17 00:00:00 2001 From: MasuRii Date: Fri, 20 Mar 2026 12:54:42 +0800 Subject: [PATCH 12/22] refactor(branding): replace png logos with svg assets Update README and branding assets to use vector graphics. Remove old PNG logos and add new SVG versions for better scaling across device densities. --- README.md | 24 ++++++++++++------ .../assets/branding/ReCursor_Darklogo.png | Bin 839919 -> 0 bytes .../assets/branding/ReCursor_Lightlogo.png | Bin 837104 -> 0 bytes .../assets/branding/recursor_logo_dark.svg | 21 +++++++++++++++ .../assets/branding/recursor_logo_light.svg | 21 +++++++++++++++ 5 files changed, 58 insertions(+), 8 deletions(-) delete mode 100644 apps/mobile/assets/branding/ReCursor_Darklogo.png delete mode 100644 apps/mobile/assets/branding/ReCursor_Lightlogo.png create mode 100644 apps/mobile/assets/branding/recursor_logo_dark.svg create mode 100644 apps/mobile/assets/branding/recursor_logo_light.svg diff --git a/README.md b/README.md index 3602074..6db52b3 100644 --- a/README.md +++ b/README.md @@ -1,7 +1,7 @@

- - ReCursor Logo + + ReCursor Logo

@@ -58,9 +58,10 @@ This repository is **work in progress**. - ✅ Repo structure + documentation are being established. -- ⏳ Flutter app and bridge server implementation are not yet shipped. +- ✅ The mobile direction is now bridge-first: pair with your local bridge, no sign-in required. +- ⏳ Flutter app and bridge server implementation are still being completed. -If you're new here, start with: **`docs/README.md`**. +If you're new here, start with: **`docs/README.md`** and the bridge pairing flow in `docs/wireframes/01-startup.md`. --- @@ -75,11 +76,18 @@ If you're new here, start with: **`docs/README.md`**. ### Important constraint (Claude Code) -Claude Code's **Remote Control** feature is **first-party** (designed for `claude.ai/code` and official Claude apps). ReCursor docs are written to avoid claiming access to any private/undocumented Remote Control protocol. +Claude Code's **Remote Control** feature is **first-party only** (designed for `claude.ai/code` and official Claude apps). There is no public API for third-party clients to join or mirror existing Claude Code sessions. -ReCursor's supported approach is: -- **Claude Code Hooks**: event observation (one-way) -- **Claude Agent SDK**: a **parallel, controllable** agent session that ReCursor can drive (approvals/tool execution live here) +ReCursor's supported integration paths: +- **Claude Code Hooks**: HTTP-based event observation (one-way) +- **Claude Agent SDK**: **parallel, controllable** agent sessions that ReCursor can drive + +### Bridge-first, no-login workflow + +ReCursor uses a **bridge-first** connection model: +- The mobile app connects directly to a **user-controlled desktop bridge** (no hosted service, no user accounts) +- On startup, the app restores saved bridge pairings or guides through QR-code pairing +- Remote access is achieved via secure tunnels (Tailscale, WireGuard) to the user's own bridge — not through unsupported third-party Claude Remote Control access --- diff --git a/apps/mobile/assets/branding/ReCursor_Darklogo.png b/apps/mobile/assets/branding/ReCursor_Darklogo.png deleted file mode 100644 index d0595dca67445d05b4500c6f938850f185f2ab56..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 839919 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

E(1=KsPY4OqwQxHPix-fkb@;^-W5#3K46m28 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 z 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 z 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�HWiAHYWJb||4s!MgH91r<`N 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%0DCT3oF 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 h7>D>Xml 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 V@u&?QMeGEzEd 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

jSAh32s0v{KViBCLHue~c=##|?m_@8*t4$x+0 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 z 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

hg_A$kYjGCE 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

&l@Yq-jE7mdWk*U#6KD|U5CoA;r!k7T#(w=e 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 Ef*@Ed@c;k- diff --git a/apps/mobile/assets/branding/ReCursor_Lightlogo.png b/apps/mobile/assets/branding/ReCursor_Lightlogo.png deleted file mode 100644 index 798e1480a4d9a6c3b9fdb5dec2f579579dd262f9..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 837104 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

8! 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%0A=qe84N7XPRIko2x zCiN?CU$qPtZrI0$MvnB)fSfvWMiV`4kv#aZlf`C<OZ! zbm=$b!h>w#Xj8Eo;h?(}caB zMX3;3sBxD}ay@~A=O3*U6|-94fBKW39KZEjzwO84!>R?p=&|eGoqML|G4wC_vM(J^ zJ@b?|v&1wn6Y=BD`fFQAf#fAa3yhoBZ;WFnj$2p9hVPOIrmNT(<^$eZ^tyr#9zIYW z7WgMU?K4^ZLr6={(=gPAk;dEyIcwVAy$i+r%z!qprp9KS< zU0u8*1rUvN*hW+fyjiuJl+9l`Adgl`7Oc=pue;I+W$avZ#8$UKDDK3=!No7oXcF2ChJr*mM2-*z)Ds&ecGIA6J>oe%6EuOu0PpJ9T#izH4#DSWpbkpHcJfn zjd8+-pzAkoj90(#s(+98+O=!0XAVOGac^UU#8#d@xqI)vHsR~z!i5Xt1Mh!voIZ2f zvCqY!9X8=>JR&T5OF*d-gbMt9Vf>*yqCu0#$^+yn6mZkk=UG@)k+?uEi7M40*~BJp zz`1>uhcFi|$m6HPkv-!0P)_ykOWAH&7G5z7Jx#EF@R4O2W$8nr=is4(W9#YwmQk?@jQy^(l0er@2-7#w+0;5y97(z5^ORwo;M39>ge{-qV{Izk>{mG`QEWb zTzL*tJt=baZyw7+hPW%n{q-m^s&i_}K-z&O(u{M2pq=q&eI`VXbRk1LV6i81%$=Mn zmM$pnWWYD#k@?tQgiS}P+V7^OEuQmyj)7?j2#8%k*FuKxDR&*`Gr;9E$!&Ar77@t~ zy5Sc+@00-9KS9SMyY6dvU@#%)Bp!!;?>oV}Vc*r8x8*N6lz=me&*ZAN4GAE6JUEw^ zqeRf&1(O9?FuMmO;DHIQl7<-_U6EC|1+B7E9buA%69kQSh49572>;xM3BVO^37nwq zY?(dr`0=fh9hPdZa5-_3g_e8V`uVDwB=L!MQt?pNF%+IN0P5Pxv!%bqZf_XVhd~)HtJLpYOEZx^-);^IaBn zi{n=Qrw%93D1!(kY<1KU+_|OyjvYNRo_qc|-{m@~nBng5ju!hYu(3Tc!9R8|W)(BSp^jyr zkhZP+&Gh95aD8{46S}BPLz<83ON<1Rn1(hI&xXZ3!7wJzk%HUclb3YFR@s71`2fwi z=o1?~uizWlmDsly1EoZ%ZM+#00{hjplAUUUH*~fVNY1qGj*L@-Z4n+vfpq&BV~iE? z2~U;VCfaQDkcSNEaDRdlvtPoMHZTr7S2#uxpn7bkEmjF_--!a3@tr*Oh`dC{d6I)_ zn3bh}$;RkT!+?6geWw1gts%DDd))0 ztnt(ba~JV@Q1cW%`jub#mGRx*^F8A?eR1u;ICcEA>LpRM$Zea*VORRrC6z7w5fJ<7 z8?uzrw~q$FiAE+m=~wmnS@V&rSFX8N!!sl&AbIIe<`nn#*L=2N_Tq zv~4O$Cb8V=%i{MMsCg|W`4(x_`mi0!21gE1!Q}HeEuobsVwd#q28y7Bo~4z0@A%9v`K45@QY*$#QIOMutw1l9B82DFHQj&?AfyFI+G1wzI?;-G~KEM->CJ#yn zl1i4@RTi(?CLAqD741;QZ4Hk#Kqo$f31dT;sc?|3099_=E?}%g8wZ9O9WgE-Hwdm< z*%#I)Ejp*N$z}BQxS*mp)g-k0y*t5s!JFX92Rvz2e$j#HI9$BwRCCe^6?iyWi38Nd zKa9U410c{Mcp8)|&`VI4YL7{|A?-S?GkMrlw`_6=|N02oH zx-_*{35z5z&V5ur6wlqQ?XkA8?ibADj$V9)9c*y+?c+r!`~3Lx7r*d%>+{Kn*3&li z1N8bd9Ww50Z;cDjJUhPZ%l?>MhuzdgHu|x0X}97^c6p;Od2Ae~nb88ZggJ|7%$N=do%fN0g+D(TplA{oe z76%|}nv)%4BG5lY;=)jJ1GEEbcqzh1Pg|P#45kN5`$5w7&|19muu_}$h2Kpo4SCGj zn#^YqsrgY3Ed}u#hcq&t13=R*fo+6`g79P(o0lo-sF#|E;Oam2$QH(sWN|>xqmeJa z{Mqr^>#up?e1yj&#mIQ0DPDl1Lj}gmnikJr_Q(F%c>fD8N(cRf5osGoNNquEa=cZ0 zA+bdek*}=i8MCQMJ0n8!?B}Y|hl?(dXVHe&Q}55}cl?|_Cv~NLvtRS~jT<*Tj~qID zP~>P6h{hM`e32BH55}R5gMQ=luYK~9-u(XjFaCmXhy1p9eq)vIUeiDL2d`&CG8t#F z7;F7qUVzP_5~m6H?BbNVMzE&>pV78ZBu|EaeTZ{e2gJ{v_ooi*Cn;GAnh8p7XMtT5 z=^LdP5juz)6DOX-kzD#Llzc59k6ui*l@SiS{FaNNt_(OYqRFR`ZGF&_(3WDtAG5DG zem@XiE~xZ*Y8BKz)pz?1DpbTP3%2zq9ywy4{*i5(Ral}}L-5DN8ne4jAN(VOqCPEO zG^{V)e*4P!=0Eu-#^3xKe`DOznr7z#-%*#(-Ikh%b#(7IDcO7b-^eOZoMVJ`lecX~ zU}=dX<1VaN)jBC_8VCdP`7HdR^nB&`=*FSXiDF}-Z6Q^s&)5{-VnupEd31}HzOWX~ zkLG|{pIpRJteG7e=_SjD>D=$g6F2%@?s_NAv|kdhR2IGS&=jA*vcefU^fD~S3vA2p z0lwo~f0?s@wA~kNtuyrizfeIe0S8oxpYxK~@Q_9fIF*$=|K28e4`dVEovMVBbryZD z=EDI%KqMFzJ~ZDhpFRp_K;S#m&VwT-lR@=~?NB~#15~ye zw$T6+7KBf&~-bi92)p%y{alr&LBxw}E_g&^swsyRpMreb^qd zEY!GTfC=KeuQHojXgQG!%Va^G@8I3Oy)}OQH-6o}O?;R~Xf1}eu&_i5I??mMcYm?t zLm&FkxbW-+)AAU17Q~oEzmZZ>21y{4_XOv5S)ApEE|C6o&gBNj_KMthfRev^oV+8z zli9k;NxI16tG?>(3jCrR;o~_X#Il^4sZDOOAT|q8v0z5g^0To#_RGZpu3}qR@h(rk zv4J~1cgEd2+vCXLL%vwSqomJXcy1gza@Y$5UxYAe^CC|N&nihT_8G9dhiajEksDiS zLsiJ=9%IH=4AUQ$hoR)>kY<>8s%CXg)C4QH?S&pxg+aG*Yalu$#UN#%jNjR zZ`XE^6iw^qLvs5!OyTi}G{2-0CutPaPFMQ`Hcss5ga%rClXCk$G|GB|X{Dj5lt1%X z?<_n0tg`hb9$|qCzT^r)o0Ph36}!Rfh$r=rG_}wdF+y*ZwlxeZzo86)<`X$2WrR8r zf$}tk*0KRMJ7dZMA&ZWDH+cWJyM257_V51gc=@xR(*|$D;}xkWOU#EI;C%mY{fTcH zXZ`h)e!F_bFS2D1_R>EV(u}C4zKX6hufRS;Kq~P==n8K@fbyb^9Ql!^y7Q>Vf7!eT z(ZT~3tq&(+?4I4xxrB>te1Df%;J1_4bq@HirpYQ&j@eA7g-rc!Bj%fbi@o_?( zd5#Nhl-+(d7~-8&1K`QKZ8I7Jm-E5Q!$+99-f^qEv1!;|sQQK_oi98s7BaKm=mGqx z564*ZHeFX1wCu^g`skkqs-{k9d>*-`l@2bvd5+MZEoa_# zV8XbuCd;Qxwe4_BB`BBve~fV4AT(TZ5yV84!A6lvIbzZWjUXZG!j0-aElM>1049 zAmi5Eev7LU5CkS2M38X6w+Qq(F?1&{A^c6O6qzXn4^xX4Lm)CC@}%@$e{a3izxSsWbuaR z#-`FHS2@Nz&3B+@{<5(&z>C{hYnj;k4H`} zTU)osA-?bJyTteXnEbjHw%oa5L&on%v-$N^=C)}vpf+b5swVCz%|8WEsmd#{0;u2( zzTykC$t_oS70~AkVLZaz>YTv`X{V!JZJ2C>r1FFhBb4{|z6pal`-irZme3&ysNB_=qR@wo0 zBO|`tRR%3S`5#)xFminshqmfHH!7jpkCKC@V2N{zT+znApy+Yp21OZEeHtq_H#f(nis25v!}UQdi->Uin$BC-y7X8zVgcW;UD>t@nb*wPsaB4 zopJK?sd41ck#XjUJ|*U_ic zU89`*>l9zocjZ&#tyehM{e?>)n(_ommij$5S9QKyh;7(KyUWBqfYyXq^qUJ7+3fQM zeE&c8{ybW<>^$$ob`7`c)?7VRccZ((#?+0G00B@Ev6d1=ipYp^WQj6JfTTE>AZdw{MGB%t3M4^uKx3Y|(Ia}Ss;>DCRh8%W zJnwtX`R={d-2kQk>b>`zz4trscMoUpbI$jDp$_>WU1+;K@#QVfG}l7-zsy{$N+I0SWW9FJq~P_7qkh#6X4+h(B1i#2awOAI{5Y% zsJ3?OHKPR7K=P#<_l2FjxITfFE76I^7!iGUmF{Ieopv< zY8QTg6E1%1mx%+lW1EISj<>$;t^O&EE%_WDY0GY}_%yi_r0M2k0`-JQtdmcD z!WW>-L0y8kKI2{kVsMgK8FR~VwZsDx4f)Ecx^{gMyO~$hh19ZAB222=#u2Z~8MF|w ztqET^7VKG^Q_R~XEVy5O`K9sYFMeg5JAZCmzIbVT`}^KE-u2%1OrPV$9{M&mH~d9m z{-P>;qU%X-x34!ERxW?^=bH;y2kGim21M7p^5%rZ#%0MXy&k8qI|%qgU!tAk8+iV* z1}QlK*)#*XS*Q^!Awbfe=n8}Rz0ejNz3vnGhcj;rEPa3ni|GZ9ug?6(x6~m}G#}*A z!?+WeUqC%Nk34#*3^%Y={1Z-8*GqcbcU9=8u<@r1OD^s2ta-Jvaz4>+UBnj*fFI<# z4&hHs!(sL4ObHD-OAbaO!b`$jVkzT*#606Od^wQi2t76$Pkzn@KnNutW8bCflPZI9 zXG|U4$Jq4s!m{Y}-ySQN%OVB3aAs0OmA4!VQ-qbzXY3*en^{y>v?uE1AW$EW)Cn8b z;Oh-qB+#-~61n7@gCTVt2;=x;g}&*sMF_`nA~Fy8g9M@3_aC2)+R!wKc`B~Y}T z0NwmL%+h=y7P97PCfZ+h;pSG&1O2gyo7Xkh@R>)|A$^dr^fFLj70SEIB_jNc5&Rb} zT^zsoi@!8J{xcsR&wk^Xaq8r0>*Z-LZvpwuCdGwcv`+ULVNn7(_X4AD}qTdAWzn`RhjUT@qf{1r$W$q zR0i$#Q~xke>D>jE7oLu+JpDa47pR9w9!GQZy@psodular5Ly>{?PKR_{H+3-IeIM7 z<##gS1u+m=?okzEOTTR>-{qD@t7Vh{Z-NfA zKW%QR|BIeT#160XQ??4wg7%@oG<3s>3(!-V>@^ryyp|*ZY95^8hadJ=MYq2)MFQf3 zbLKUeXyM>0n?Y7Qo?z?RWmw>4Cq95sYJJQJnjb2NHszad;wVx3S91hlYql*0*OjE| zFafmoiv~~LZDc(-AsNoi*78c3zpdGZV#5GU#X06Gw^$OZ#!O~=i*RT}~`skri1Owx8?(k?Ui&)ACh9anhBe0b0|6-MqQ;3aGr)EAUtwR{P;M0t& z!V6>L+NOB+kI#MX^W*vFp07o304;|PuS*F}J7pEy(#>n29-nF(z|)k#raX2;mA$kw z2b5wm1n>R>iIeAs^bg#(yq#}4c=W1>BOdqm0t5n1n$NQcS3_cIxxO-r&%B){ba6O(fFo}jD!O}Xp&`Jfmq>4TPE*=qEX=l zB&}2FQ2RziDTid5)hUPBVFFi3%Nygvu__(}J65Fr45dgD4{XKiqC(98o-^ahl3@CKQqz&u@6N^U{kMW3K- zH>OFTC%-E3m7b|gc-XA6Xa@857zj){tXM}CX;(HVkmIc-U7m5lF9AHN-~}R+<5tj` zI^N0CAL(NghD-svQjR}3)aBT5Zx(8{U1M6%Jh2f?tvz8#Uu`6~_ALx4_rbb^k8HjF z{on3iFWB1B_1H3SW)sBPhbvDo9OVN8fl`VlMsN6>iK0oSq3e-Bmu#oYb*gVnAq$&y zkJoPWgd{=u2Euhvr2$SlYpFq5#O&wK{CcPf&VhP~JvoEXCP|!1?w8tNf|$ zOC~-QUTtsx>k#TT+yeIaVk{LEGBS zxKREmP#v%Ab-8u>H7eV0J^;U{%T7F#qa=M7vOR0P0QhAYfR6)NrBmF(Ydg-y*0N)# zgSJe|&Gen%b|Ev_V8SW?TQ7HlFlZL&tq(-;7WgTX`HE-Zzim0M76omr^eK}k7^bMq zYs18{Z$to*VO3!rJPnagY)tu~_v_klvJuW5d7j1Q?$xrd%=VXn(b#M-zv|(qhlkdD z0}u^vM)WCVVYRunHNN`Qua2{4&w3GM9_~IHZi+`|=|Uaf9(v}kyT?1;@%C}#$kDOM zH?q2Zx-e<8&1<^(ren0^QV_pdp8#FL`+_JmT!0q=)c0QmP`PAmV+9-l;W1|ioS9+r zmwJ)5eEX%BPgP(0kH)vijkd{h=b=)_wsy8nPb&-C@Do*Z9);)!wb z!o_j$Kwdq(A-z1M-`w2tw}Jnu@BTB9#V7YA*|Ix4N6hB}eNnT|5YkVeCIo4N+^7W) zQU%&9PA>o(Gp_qwW1u!n{ZT}J#z#0Vbl~TkHbTOqK4w`tgkK1mj*rtF;%YWrM_&a$j0q!_X{9-5KkMg6E*lAe8O0dAVHDCS<_}(nG~8pLjAJbD|^Wu@PIg z+y1$PwvIyceZ@cB;zdH{4M!Hg7*k4Av)FUoV$r%ZFVoWPBYna* zBgN~!08(c(6Q6d-EG!sZ)X6@fQ&|)JUl5va04(I~AAl{gEueg7YpLrCE) z0x$j^5+8iGB z=V9}6EOd~}R74XC9jEpsud}9qhatT)on~Pe`Hq3`_Hp_Qbc1xcO+^LV;iLKrzK}BSW8?RK|M$knKK7&IvBy5^pE}~3pm~+opZzVp(Jd7$&$(cDmD67If7#&rRO*XCmtTB&{9pc0|Htuf{#*aXxNzxG?3vCtr{~7td=pvr z)!(yLY2B;dpqFr2O|hhX$++mmt}u^PeH|AC#B(lX7<`SGV-K(OIFC*^MHjDQz5o-&plGdV^Pz*Tm69T!a7!B6^f9%mk3K z=BYx>e=Q3MeFo?xzLv>G3@WF*`!uhqhYikX*ckQQ{YHA9dK#4^Pcq7Nc)*17Pket&Uhvu|li# za3@{dDuYLd4%LHv#viEee-u!}2odNanl_h6)1@o^*+H=r7Yvh6o4`5ga>3dPKyVPR z^b}yv`56`B=r0KDx)HCAodG4-GBm!fO$4$@6YS(|u%e)=zHVRg8t+-u0IDmzQ+<`+ zull&Z6%Pw8`W-Zzi7txx?gg2ukr<@zEuWafi2CMD4B&N~sg`)%Z))+*$40Q5{)jLF zlJkMA4s>;a6Mdlm*z^MU#1m2aH1nj@V9T8{kiH{+bQ2Bq;;a7Xqs(>S0~n*f+9{X! z%Ln^aJc+Zj0_vqd*~6E_4JSy@L*;cA%|8PoU#K%kMRFWnU)LOaeLVKr&yD}`zx??4 z17+*wW+!p`xAn~6q zwEZRSUpC+a2hetR`Nc^^n#`Fu=ws^z_Tq0lnFrHPGfvX4LSq~-9?D0z6?{IwrXSE~ zVfq1F0tew6YIXp77Y!tuYbJ#g2R}G2UA`$ylWg;5phKlycZuk(HN^HY*$& z$y&ckWx*JO81ct*^3;xL6R#=xi9h&d$LeW+rL20f#oT7SF<7eM&GkD7BX>c^1n5n0 zKzXVzhJMSyV3yRVn>aZ z>qPjTvx^2 zanPUdhP4lZi6*x@v5%bt2iL~A^RJGte&s8E)!E%b69cc#5&!Fa!I9b~iy>`* zrSt7?fBQId@4bGC8H3oDn6vSv;o8+}e%%*+#@3{cOcr)V>YqAMPw|;id`)u_e*@Ki zT=ZA)fv$J*R=WyQLkVox85aXWOnR62vO9tDx==C65-aXHW3Rs?1r_)Lo%;K3v~YZb z^XESQxpDErWxwX0jRpExz^eWVKBcM18xPdLe}G;f*Ln%Hg$YWWlwcW+q?b0}`j=WgVO6+(zgyLl}kg#a%c^ z=*@-BB8mFDUcDX6*!J;@a>nV@OvV(A_4hgZa@`&my*OJKD(~?Qt~ZnwW?=- z+=MxXx|(3F_=LayIio{|{9Eo{{K6N&9=N*w6t%|!XuY_wJ}Ie;Ap3!8QBb)1Lj}UP_JL;sQAnjj#H<`-~YS+`8am+)VO->8ogFwL1v6?UH=a5@3+z#$d_&VLS{Eu0ybsrw~;=Z zXmQi4fS-g%ZPGrvAO-V!+l)mMSg+=AFw7&Ky8-NU`$Y;U>jE(0;qcnB+RG;ihJ&+o z3S~RSb1S&oQMuNVk^pw}1v$aoZVQ0Pc9}~MMX1*X2Q(E@f9Wk*tl>kT^pO}h1MOqA-qK_K!zi{v)<_HwDIX2=rPvRz?_R5(70te9VUaa@zIwuhIDvz z>u|jQWXZ$3vtH2~XnxX`0XpBjwNWscQ~R)#Spqhp0i6mQEb;FWDTM1lhSM%4(S=i8 z9ZRdy$t|9IODyj~WkHBu$sjJAo5W#Rw2CJ*O~*D7{nVGklXMIw2FNQ-Of;cDGd+0U zdAE_e_!v(N8N^@%)8v7kzH28j=;_0>e{Ax!~T;?c@0I<9<4gjo7U-N()Db@MU{DKgWT-B127z?-esI^yODCvcN^H z3rbul=wL~B1-}3cL{VT_ra=J9>Tr3%JL&ASXY7R=24r+G=WZq6 z`u&wJf7xHYL)-Y3ad^2KqAJ1b1*!5UPo5m_e$P9{efQt5YHIW51-y7v2iiCNk$5fq zb{&;+D35Mlr$+hu`uf<|)Pmq3i=*m`$V}r(hh;=FJ}~ts@=?5l?sLs~MOT`Od29CAWrMB;6GosTv0x@TC=z>ug%nbw- z&=;d?P9vR7u(Q^avEI7i#Yg1JfxRG3Mqc(EU*V{8#PKK_o8doNt{_|SOtp$ z?z7Mo`tv53`k>Feq>+y;7^66C=3HcrQ@(J>bmGH#_-HLb#dczwPf+cHb3$c~%Y5Kh z=FQQd_N6|E3hb}y=wV{s)MwH~M(Ko?ZpILsMgO7!IQ%586>sJ_E6|a-kp8A3n+Ao% zH;Y`UYHP{yGEH^`ZHEIPPARd;RY^L9} zvO|XtJAM4|$H&k8+|P|){-s~B#S1nCncJ6#U~D{_LBdRlhQ29#kCPPEd^9Or~Fx__K~``$PH z_7DE8{64VO8^tbuUH>+?ChIyYRhG9tbG!zmU9-urc52zqQzYw?k&e0JWImAaDeopS zQvq}x)Q|d@9bRsfWd88=3IhLSx34`dpXih2nXB5FaLJg}IZm-@aq16`iIP+XTg$%N z9#+w?Y^SLPE1C2WKT(x`T(_robQbnq{SrSVPf`L$9S$7AdS5 zX{a*YODhq~6Zu?40C_9FEhZrSwtH@Gf_H*8!IwM631S5kWMWF_I&Rg8yR%M#U-AHy zgY%NiENKk%GWf`+xd5GQlYGmPfOp2l8L;n>H^YKAlYw)##{$nN;gaGPKA;yN>2kIf zb>%BC$H6B-+pW$mVsGB!1M!KD{uawQUgGnJsk$~VBqMS(u6+t*@J%%PgPqC()C-hx zoWNB&>1^hPIgS~I9T#j74^#+)oF_my0Ahx3!kLK+mKGm9<7o21cG_PDexN53a*x=I zv2|SwkAnxrRc+OOTmT(c79rS))x?@KvEZodq&fDnz&RkR2iC@O&wWE1;KzM2Ip`<9 z(#B6FDZ^ri4@mM#E?=m1=N)&9cRuotacKQ;o<;!WHtpt%p6gQn*CfmnP{0>f>GVQY z_-sgE2d|9c!fz~hOie+T^>d0IfN8FIcEQws*sm;rjtK1lbOS|0zIX`%Z3ZplS3lU3uVNYKWO^0tRsO|W2o!|Y`?~SLQeA=%d@_FFC%T0Z6j_q+{TMPHC>*M&b z*O<*5ud`jueceaB~M^rA>|gx{XlE8A><-Csb~ zSVOOSHGWr&=$E;ih#v;$sXOgPJ7u?pngF@beN1}M3`o9k;ptQeyl{2wY;!lDa$>I}#H}++t$9Ed= zSy^a#wHP^RBi5Gl*)UZX7M;vZN}P-%3_5k25=)OAa3w4{U&Q4(*Qn}C)(1|!ETO$%2OBKJPYz zR|#{LZ_Y`ESmpPyTSy>Y-?%6pzF}KFheh^j)_B>jdE# zQ*Q)HCt5Q%s-B24&TK07+#W8a3|IyQ=qO&tjYGodnquS_G;eSuK_^n_tA*5m-|RF? zvg4%}UL60Uzwj5v|NcMx-f`*D)v=vUYW>*aZ8d-1-G9h(=5VES02Ldd(e1Ed(>8os z0sAi9%eOh;4|{&H&;{di4We8L1Q_*Sei{W%elRyQP)R$(^@*8)xd3U#n%diLqg3&7 zq1PYE+ZdXwj*N5u-L_>{B+sQ{XPSc(v3L}^Wt6xd*vC?95YBV;gfJfyg=K1txC)?Q zV{Vxg$Uyl8(W16pQ1*&Jf2#8mXS+(35RbeigHJ-Ei!jJui?l2=s97X)dlUTnu;Vkq z9UnR&4NRHN*LZlU(+S+D?wrt@2cRQBo8{7Z$%i+cNeJV)&@q@mnP~x$^@YpoS|<=a zx$u%kcD9;4oofdCU6z5p>yTrW*9&s^Jc1hb=G_gk<7!vEDSN;x56)^P-QmGrF1ny( zn+coLy!eb>WF_agf>YTxpxMf#H#$KkW*M~N6~8ZF){9T@dNolv5YjX)oIrw?UfJH< z+VIcj=z4`VwV4(eD)5C>Y=HOz7E?+tgR~YG1#ZV`4qt0!6Ma`N=XYb-9LFc6mJoB* z%OSF|eg198XP|^V?&Fxd+)t>yzOmo_mg85Yxw25EgXx_Y+%8W z2RdztAAxEU<5VZ|6cxW|;VDPZ>n}B6Lgf#1Dk2sfCJ%f0GL@4UirojW2e0)~Ey5)- z{Q-;DeL+iU;uoNTK9(=ufFI%N3j%H`T)TX2yztTsKU;JiXzjZ*-C((r@mrc5zG?+^J5-SHWby@){3{Se6^0I{= zM8r?qq-h$vRabCb6)*ghQC1)&@|Rb^xzW<7rUn@-%h9D`+43 zbAsN$QFi+xhaW)si)0YEXqvwW3X)Z^2^5d#Bgx_;s;y7fh4Xmubtt$1o?#aqH^;TB z8;a=x-<&zXNwHr(wTRM4p*wSK>X7=X9(2ZHPa;Cq&AiCL&zJQnroO3+jgSmZIJy5R zvy@lSUqa)yHj@v}drP2F$%MrKf97^>pm{DMu=0ViKwE8Y@bhU0O-s!2PjMv{^i$#p zIsujpb9B|i<5!0SiT6QmaQV5TC%^vW_^DEdCw|pGeZ;q2AK~}KnLBMiGR`-+ zT9e~@LfU$kF}H9#`wToyGhi#ZT@XIAOwe{(hx3*G(LnP0XMS!~xachSr5}o|?RR-6 zl$=AU{LD+ontcsEeboKFaRNR(!*^;l_*G*R7H{K{RUb4`JU*9B`jqVL+_7_l=icdU5>K zzw%ecpZ)IdR=>aE@dYs4VWoV4j{sG0mm6s*^tnsB0Q;4l`Xc`Hd{w?UPjSh|0iKVO zO?RSU2oH@N?LkH^>$bVmC@s28(QS;!4P~rDiR#D~>iK43)zc_gTuZ47xZEg}B_00m7N^KVPoF{!GFC@kf46@kX*cZpc4$XP4eNlqannh2fa|o9 zDWpp}kU^YW>u6A()^X3JT>4gcfZ*wbcBi2l8?qOt%EVvL>M%A(nGQ?`YQ3c3I|cU2 zH~%eojlLD{Er3oey2S)^TE7MePI2%+r)*RPRSH#i2}YFjvP}RO8iWHKAu=Eru*6l~ ztmLJ)#VE1TksdFObnq0FHcQp14`LM3j{MvNi?O^i3z2UxWbm@l(!#Jlx8lV+8xE(^ zC%eQZG<2rU-KMl9zuoKC^IVldx9w?d~PsW!sjU{T8g zH6+@Dw&hE%p7`41<4a%ovVUd;-Fz_`pFinu{UvrhaYEmN4?Q&A`=0lV(|4TqlYiRH zi)WfmI?G$fCIy|Qd_nUeCwco+m8V|Lxq@&7@BE_Zn<4bI1jHobV<^@Hj12tBPQ2BU z#wo*zf)N=f&KpQei2;9eSC%@$Hr@QO9AhB-L=vzjoqX|Ay6m`V_Yk zyo4>jL=$~7PMXHlRA2bgp17;2&w+xD;P39tKDd~hYp zPB93g7tMA`b>a&H-JgZyXTjWtl3^jpO^{qakg3@D1YZ8@;3wzsdvkls{p!Ge&DR!C zKT|x|ei{66#4Cv>ffkKl!lHCeRqw+-snT z&9Aa=yuk-6_5@DM2V)}w%cs5WDiDQp+^?%-r{%+nkZjXt>X)`e4WCs=}EJu2;^;}9Y)&`)H3$KwLXZ-Q?kW{ zt=udXZCMsm;@EsOzbnf;hQ4!W&yJ6NZI|Xn7 z*n>w|D=JFcYA_SLW(-c?c>y1M-H4q~h1Vb5&hsPkU{F)yMv*7YNi-1DL^GRW0X^5o z;F<4W%~NCIFTBc?n1esK_kzTWYZrbCfqqW*AH6#IdQwU#CA!FIeg%)8QsApv=f#L_ z+YtKp7h~;)X%p<=(@;ds5e30P6qSY{!E}R&hYm=mpkyuJTdn~<9U7cq&1e0&pfl)E z9i2-#^56h9wM2R%3Ci81s54Y^4zr=@PCF<}P? zCmjri>CQR-8jWUm9KvY;=>>b_Ok{F1jT1h$-yjykmNk>|$dx^_fZtu;o;>~ZMlv2W z;$;)VXQmJ)_8VK*{DAAw+96S?J8b|>zItZSAskN$vq+)6nAlN4eaNF9yPTLBASO1@ z0@P1@>Wk)AspHz|#9Kb_#9%`k<{YvfldE zw~YJVbiX$gUP#si=U6-SsgBo!Wt%j_SIfICy4-pLRK@i&I(?z48Cc4a2PRzsu+-1B zUC`L@N3lFCQRrM``L`b&Yw8EvAr=3?Pci_BC0jg5`**rz`|o_pq5snNn! z8wfTE#2Fprc|{8me*gJ>-~Rq__uXeyzUd9HtD-n{cLr#|uC)6DzSwA}NHi|hDLw#v z%|Z0P^p~coGChtstg89|>f{F~2uMXP7~AA5{^i0bZWT>O%TMDJ#MFO^HWzd*OZZR= z3U*uZsrX=ZR=m_zDdA#6dBeIB>jY7D9aMzCLsqLPvwz}An|ib762AK1vbf>-vh?^G zAY|X9Gmy|{%m_fsf{pQ`m90^XdjLK^p}=?f03Ushkxrr8&!20x%GA@u3@eEa)IxvJFil1$x2C;W-mGjVrtr$d(Mb zoneKfcB37@^=tO9b6Tj>zjzpQ_D?huV#6-FkATOH{t3C;2qqoY9bRHuszTztVvI6; zl(D2X@&qBIlj3P`Wdx0@j~~FxC}N`&N_6q>O|tzt=#-lxeAfbBS_N=z@tiCleEruy zeUwe^<;$1Hul&kC9zXKY9~m#c^n$gf7W^X20+vT9$-XF{rMx9{YO>*2z;0Qjzo zkgK>>l>^uTu?NsETgJ{TJTGcY z1)zfi+^>ras`!c;UB%noA_CY^cBLOBhOUl|{&s$%iihaxW=xWJ+gH(U72lnJU7NH6 z`loCl8q!mFXUt>fIW>eH7NnF`8CY=Xls=EBc`O7Wfc)h9iVZ=RsVXcw==0aEUQxE% zP^ZmJK1Q@Pe&Waf!8m>Tj&Wu4YGPJmFm`>TKCLJ__i|U+^|PmA|Y-em;J=^uN720 zpofA+|8e6rR(04W>jag&T##U^hE;Nq|7kaOBw9x z4|W%w5v@1DFrrh5%@ttNpWHLAxeUH(WssMuTF(T)?I*#zVb_!3-9QH+ZgcFo7$>g6 zRcoekcJl@YWD#Hz%uLd5RbjobQiE~TCKr`~sgned@n$88q6&ifoKX^+9-MSg>us6W zgFWg%PjV4Im#|lTZv_duzk5Tk?&+{l!rj!+u_8zd0^l&<1pU z-Jh-9;!C5Xm_PrXschw@NgRn^l;=r0Wujn91MbK}yh7sjEr1Cr;rMd8X=-qr=1Z)?8ip1a4p z-u=#T|NZxS!MdrFd>ZY(Plt`;f1wwrO;-DWyz5gg;-F#8~u`V$<2=;y-+(^qH8#J?}RugFw0X&8K4f zix>PXkWGr_sz7$Xg-s`qFVV28`lGMExC#EY4dj*Fs$Jozi^B$90^obx`w6g87`&ji z9B0)JA5BLuPjs!!|Ii&*FzE7>C4J&yLyl0(+CS=pAmJ3hpQ?)P_!Uo8JPR_iwj-MO zC?nqe$wejR!A~2qauBwgr^aOBOY5^X)z!9*K_~GbSNiE}8o&0Pynwkl_F>c^KJ(k8 zmuTka%jlv^G>`kx_Xhat^LS_%v*(Edp7Q%Ao3Mqx!p9|i!75)Oxak|I$B!N_d%|lF z;wm@O4j($?`u^r`{^t0|M?Nwh`|M}N9jEUaCr%s}ecxaj(F`tq^%GD2EH!bOZQ`l{ zM2zTPeqp45YEtz{W&tx7fL`Ro|II@BK-z4wi7(1bwyRv(iHD5w%D2p((0F923Q;n+Z)9oS`WqNR{@7jIJZ(o;ZBZzjNMqv#^Mdxu*b@KBU}v2aX;Bn z>hZ-Nb4JqzWMhAf6UUGHrvwQHZ?my>x%leE@xc$gfBg0T_g~X>_4?TI4Muc`UTVAn zoW_3aSuxJK27AE7LsofWheA-a!FA?Y?1Y#4X6{Ov#HOGd5-S?nmyja3Uoiv)#vse} zm#hemV)@*3*rQ)(f-Hq;AFeB^tNw^5^PS%+;7{b~h8PJv`g5Q2+*1H~M;lCFIpK@l zmY6>%tADmc)=tuHz3^ZId{m^rlfzD`@8~$wT2>(v*X6HkV;mY>FAilK0~;fOi)(|_ z1|@#xWfcT@cL{Ui5ks)>++0b{0~aF~@H3h0z+8bPzfi47X_b=xu18 zg)46Gh3v9C<>7B0HN0@~nWJGb2n^U=;Ot||a5SyTHK1o-+V7>_ow9pCEh3YbF6WU6 z*bFD3JONPDp9gG4voX{&E>i|(9k$=aCYQ_%((2I#7Jt)zs83twg2^H=o8m|T$z~$T zLKWR$_Icy^;wvwYbFZ8o>xU1IGxy);g$iF-#C${wM%s?~0r~`qlG&<3#ih&fa zYZHA?3woThKc>Ko4*VEnO`EK9=P!&eed!B+rTNg>L0?38#f}gkm?kjQNjtWC?!0R} z`pBc>pcY*4IA*esHss)AQ>|??5-LjC3ZN0MC13$!JKhZp?BGqKRUzPw4OSE&U;o7t z4LkKV6jR%&-%#AC_twBf348c`$B^oy*ZoOHn@|R|v>9Js_0`9p7@zTo_CLTzx&<(*{F?;&Ai$s%6@#M4W-m3)HiHq>SI0yhzkpc^3&s* zMK>vJ)qP)yFKUb@z>6vIt+W~a6qU*gPhX7Mk|{7xjWa0aWtbr@VQR}h0Bm<&DZaFr zbu9USnRn%Lp0)`dVb#|p+O6sZzv`P;P0>5sb!-M-lG3`VyR^1GW!fb=oIg)VUPx)w zi41%iGvXCSWyx4HvVIaQ1S##pVuU}wDug!TOXjX?!N!{bT!862d`yCQU|V#)&D*cZ zE6)uR-VV5S?dsU#wR*v}Wb*2?`rVDl@fx)^omxQgO{gq>m`AQ}<(pBDtn-b*#A3}~ zw&thM_;_$=V|8R4J9;I(23ZYs*Dd|?y(@P^*=@YMIoqtkLKP_jDm zD%l@&8Cf`VMIKDXWn_J$q?$jt$Y26)CCd0*aARD(x}kWkmCej60I^SO6gBLlK|HYa zf)uP{MLUbmmvo`vOJDx-_@V#e?~mX5A^Vpzd$80brGcsr$$e!!!51yT0c6BR% zz)!TYn`>OG>;$l0hv0C_kSz3@M#?Fu%F9>NghU1!MU5egM$x3JI6;NJ0;;gaI-`L3 ziJ$t@bZ181ns`NPssHVN@b8cR*o>W$;mMei6McPTjK%h9>~0C| zoa>{MtdRkuY*r`qnhx8dz8TgAc;_~XUbiPD{7fS&&HNeOg#!8p*Cx*o$iSnF>ds$u zf`_+@v6pp$`1zBLluCX9E!Nmbt1N``^GWVVPtVx~;#!*Fx1Xh{6)V$q#uv|f3m+m^ z1pyTMT=GsiS;iC#(PtN8rn^fxA3lo`Pvj+odlQTPZf}Bj!!4c!ucFcs9aE*y7ICc3 zy3&y?&#?p7vMB0ut18lD2$+q|H~|Ab8+C*NVM)jA@(fEq=){XMe3pp-I)KPeL_-E~ zD~^uD2A#swX%~LZAev`~Dhezj)_%(2?h708{ue&jT)V6m`$|~gtPJd>V*EnE0=ENL zvc`gVt+4rZxDJXEkN6tk!7ox@(9B{~V!qE`jKt?~z2#Kp`0Uo5cirVhFu+7_p-Ael zDrI)%xkFg-O&i=CSFc?0=fapoSS%Z_y0c;<&nwU`zV!0=(igwz2=Mbb$l)Ig?)H<7 z+;uI!A9(PA@yH{O$Q}!{ECa)Vbf3|UxAG_If_Fa$u>>f{a{%~WZA5(y#Zwd7vR(Q@ z%|(^C(T~!sC1dC`-bQcfP+N1sNJZ%{MowgaI2BnbZ7O-&#ZMvqnL#FPcxtf%S$=Zg z=Gw-U@duy&!|}|s-|&Une2QQ6?e~obVtMDCca8VF_uc-CHE#fbr&cUlah*1Bk5(NO zVQo<42gb#t8BgN_ zn*-_^Uh6YY=zz1W)9n#G;SLW8rop-!S-kZIQrFPZM&MNN#atuS@zfvfE%4@FeCjcg zL8tM=+APAeAVQCLJYNbYx}SoYCya@Uysf^;ML*eGjm3a5=2n=CfTZ0-3OIZBTe#VOxwAA91pPa z!Tpx_QD?4+k`T@+R6oCMB#1rnNFEhvWS-Jl1=%u^n8!{a)}zdsI*^eWjcadsiG`hF ztlSt^G-q?up=GECho96<^68Jf`h4`rk@2;!eRcfgPyW>SmH+x5k1N+MkGpi;;6^HM zG|)>dC;iMJ)Z1TZra$rtstqU=*shZ6s=uEkg3wVLDnel~mjdo<)-!|E=(I$)ESa7B zw}RHawCnaL2yNEac5_Pn!u~ooT~7gRX;Gb&Wej!uTTii}*fCVvqPK!cq|#MD595p0 zAn$AdgVo_&5Be=>`35r^U3W#s2QqXe(HY^bDYK`A1S)<>V@%F z|H}Vk{CEG%pBd*aUW%;M6D$2mCT+-kk?(7e7SsLOi@;{erxma(C_r9X+z0}AbFp-h zrt&36`rS|Pox018P;Od|(z^<}SV1 zfd_swl%>T38W|;bO%(2h+lK#XJTl;7P{ck;ZD_@vyElPoM9Q4 znK$wrvQs_)t2%bdRvEH7Yjxdd5;-16-V=`ebhU`D^2#eZ&Y8z`)`INfdP3>4)A(0wa<&$Z+zn$yvY*8KEu8rfLdgN$W(trhh&o%?v z-hy}0AE-y%=fu%GM(V6Gb#_027Cd>bBac1y2mYCx<2&~`XF^?L&RoIs$njc=-nFy zRz$zdLOy=&ut{C)=d2UAx(>^BkKXVm{$P^N_{zdBnlkpgHjXWN`IBy6gcksYKEAb? z&s(}$_~7b^Rx#)EmbQr5X}hjf2|Ipa)G^ADIQK!j1@m39`$Dda&T>$;j^Iny6 zvrrk~vn)_qD$qh-YO z>vibxLEi+To_-2L+<05Wb4`4TJaJ?JDkbO*)^?JB%MBtB`7)K_aZHL8JgPzIltc*G zb9~{EAAIkED+VLsH9-dnDwI#OGFL@X{t8e3@gfeCh486(G`B6=V<#Z%TFW25GebYu zAK$Le%}HcAy4{?&U;D-(#qsd^;qj8L8$b0^KjkmIx_b56xcA=s$M#KbnpXP(2$RJX zbSgoij7$hN8wgZ@E29Z ztg*spJq>RBT({!y92c{zKzXW95gnpE06s(cy0fmPPO_b$-K(TD{mcYq@Fz&-Dd%By z+mt*vgy5_8iVq8&0Jt4K`6dghO`h?V0bjy>vj{R{7`}zCne?FE(7cdSx6ta&-K_-~5~7p*KG?E?vI5;-7Pp-QJcr zy1sJr4v*~tbAsn1DMc?JS)1vy)6_9HmkJQ2PzbL(-Cimnk74CQuD+(W0zch&s9;By z4FBK~6HD0 z8vca<-w;e6LeBB=`b%_P&qkAVLsiy!=$W&nNZOqoEc3avln9ROk%au3jewqLz~12}V3y(ai(;*>hJyO~TfI0Ej{rAl?< z;y%?!elS@=L=aa@+S@ON8`xr+U=mvbxA}Bon58txy+C9k$KaBL{IINrs339e3TGCxMoRi~Y$T;=4oIoe#H{-j`0lguMJe@x4ZSTdUDgnh;FrGa z@GF1~&`8E!Y@rtetphqG;y~bqhgA8hy}j)(JLC1%3l}bUGjie8SI5Om7kx9!^Rw6w9$2%izd#RD z9wYe75wH!>vq;a=-2hKF!q@FJ#T-UR_Q{#KKFT*2h^`M@&eM0jxvLn^pgnHTMNF+S zQl8Td#8fRo=&|RvP+u)tZ}9l{jWxxYk9Hhc*M|7`aX&#mwti$BIda5Ll@IJ+^G!I5 zxH%;wo#_iwEv-Bw@C`h#`sf?99nN+8>wu0g_+HKAXAAnz4HSE2UgBwwx!Iw_R$S+@ zLz&mkne$xApO|t`U-f}$^I%_u#*X;}*4KG_gjEq!%8d*6ap|WmoafJF1Y(UgfDUj2 z;h19f%FC~eU;fo!9Y6bXKR2F!>X~um*!nnq>Xa7pht(f9bj^rfTGCA{Kv!j>nK-Gg zlYg#+63RMw&*uPT*P;92HwPKVvD*E$%m2c_{&gL`RlujT@(fjHP>>gP=z>#Rmvt-b*nRnRCu-4u1dp z-ao$oZ~pbMxw$#EnDh15Y8-RPSsjP3XOsW}$911rFZjwYqezi7O@AKWDock@#>3Py zvyPBrv}i!_({BLIzRr`{l5*2r5CvKL>rhD(O7!`FH9P<^9`33m+}+1)b2(qJ|F9UV zj0Ko)1+xNHm25yUNNf;gT)87wSXrMbl|J97S@vlw5tHl5e26?nuKJqKkOzu4iIst^ zYh-L2>+!$}Aw0(F-&3_jU?=Nq1lK+xC_7lTmATm8*HALIH^IB%HC~5)tyqOl!@J!k zNT*osa4@t!WYm-v>V^q^=F?g9dB8UR43L7d0y0Tmzc25Zw>Q(z9nz#Y<&%? z!%kitE8k~2XblQyi>9Q%MX~R8!Qi@j!NWqJc%d06BdBAlC&v!Irh(ghK=JNsA9w+9 z(Zv^-P!HeCuy4?GRFMfE+Ljhs-+1mD{`n&4aIxv(6}S7}biYs~Uk2u);!`tP4!CRsjYi@zci0{Z9Wp&^mB%|M=u@eR4ec z#MianKB!pT&_>|cc;`DG8IL^ruCc9{`g7m5FE!YaQR0$v`hD;kUBp`D1AMU!JS`!{gzG zHw5(m%a^W>D_1Tnz3dI|=Cy17_ECR^SA4V$Uu4FOCfbM3)uw%LTnWx8Lv-bp&MK9! zu7OaFp-NEw)Kv107YO;|jUWE1%vj@N2Y8Q^`BDvmbjT38{Vl`dw`DSA!;WzAFFFF# zrc8GHCQ)(OgS^;NSYE*&Jy=`X$V^7tS8`Tzd-%m3H!8|N-w5KX-0 zll{gA<~YW<$82;4%7)U64#sN9;h*!K3BpEPjgL&yI#Vy^2gjw`uR!>z?M=lmQJDk4 zbo&ZYGaVLgUil@vMp?hww)~=c;BC)-x4!fp@CGwb|K>JA#~u(RRakPBOw+RaGijbil8pnl53q777m_L&zd=7!a=`Wm7nMLzcPd(#{lou(Y z=jrhn4?XnISX)2j#W}LnVYOYTgR^#Ful|*Gt_8Hnq%82Cdg|%%wXZ$yS1YYX#5@ht zqFW1ifK5CW-}&e}$D8hd)7aFemN=ke%Nu+xUbTVlCk{;H(Dw07IeS%?QMPWSb^FUF97|L`;uN-)RQy zYw4YGAqhmKuT)oOac&J3zcIf2#V?NMpMPoGb>|)9z3+XG7rdLgShFei;zWPFVCl)1 z3p5L0Qyg>53i|jm~#PB3@R144l1{clwE2>1MJ3ihBP_?OMxZ6Au?^RF-u

xOxmo4So_N^oFk0~9AfF4DH0_8RjAH!o3?;p_ zgtGpC_{0ku-|e!nys~Ca*D3Wf2%l@TbQZ3^O*l_)!$Sz`R0#V#7)c#1k0d zM+b3Iq%~&!iX)2;I4oN|&8lPzk^>InhF{$U$Lrl_#cmc698{mS!d5Wu*Eq>xt9%TD zg$D7z=^KE@Pn{Y^j~>$|@Ax>rencDNW2y@xEc$FtiuA97%xRuf-KtFzw6-sP`Iwfd z*y;c>R`D$uyCYn0?qTHBcE^x{8$e9fUx0nuoV*&{i*gr=mpn(Q*a>;dV~lH?8~%bq zK2zP-GwR0JKXRB&?&kQ--}ue(v5)=e_{?V>8^=$abe#AcHvaSKJ?gp1z!zXq0l!6{ z|NO)qRK?m|#tzy>asvBCyGVq1aH!yRs`z}XVCm^3eHfL_9=61~gx7s`M_VuR0_uW$Q@jdNF8%t$AL}exIGrzj7PT_TkO!m~*_O-P z5uE|*XF-=NFO-M6ZITLY5ta1McWONU;`8G#f8Y0w|KY#>ua8$RTnsPcz1AfeXOUyN z%lDyxP@(*vZ6~gP+rYVnkDkkgCGM_+Xz1Wyc-9bX=qv|s&975liBGOON8j*eeWY^r z4V-nfI!@g9FgkQ^HhqE6As0%jbR?f^C-P8}_Wl8v$@F#XRuIX6WrT@3EJ?Ov3*hGR zCI|es$scwd$2LZqm^)^Twoo*>KN-sA0(?DC3J=#A@rq>1F|uD5rGwfi zvRHZYsi($;S1)R@cN7J+;T_|id+r%0PM&nzwaXlBgLxC*xwhd?Ttb#i;td#G{#rx} zEH=N-J^QTf^VG`UBBBKh6ajst}k}5XPORfFpy`z#Lr{-v!iBgm0XDOL>}PIBoi>3UN&&~ ztPS?G*caYEyC7bVarkxgXS8&Z%Z1gyb(SobQIChR1D;MrlFhJf42~>G8_hvtvUW3pAq>J8V$=WEUIuMVhGFjcrk} z%^2aSEdGbDUn(Q!-ps2V6HDp~!JPIXc$Kgb4QiIi+Yj=} zv7340hT^#;o_v!lpMPB&C$u3xdUV}y$J}x1PK8Z$wIz})U{FV!_v_<~o3?F7h!I)H zCTSeVY2Om)zE2z+JE9M-%Id`EplrI;iw?hvq^43`jc4kY7^5R~%(#N8uLSq{?wV=IG==hZa%NtjEtiJ3d4^QTq za0utq!glFef!>HBrP%O?j-6nf|N^qYjl5WOv5u}Ic5+tGhmAOsIkoAe~~NYXx*&I%S1j)jZC zMH%Y|7wTZ3q&=*LI@TY-KtEqD$H&Zm^hZ8A-t^!D(1|_=&gGyy z2bC>vsI40!C-fB9KT3^L*>#8wvWXA*@VPB!4c53PM5qda(%Cr2#vRcm(bb2GW|yYL z0KAedeYQ_qsti9zZid1ioV8-kywO9_E-bm|hQp0wn0Y(8kixT6-2+5ipgEWisuMLVTgYsp z?b&(g4MqoHJ~HMdPsc76CJnRcq&j3`3N<>(Bjagg1?GjlI+j(7Lm4OLKr-^KP(k#P z^GQkDCBI`6x{`I39MqrGGt?W0vlLUdyGZj1dc~G?8b^l+6#N5mS<$`LYFy9)@E5W zCRRPE!Vpg=BS2&f_T+5gigdxs7ZOosQ_7ct zaoJ-`FI#G}DK0h~lb=IF3pYW(k`)=}E-pa_9zkEb;-r$Ij z&!&6xZP~<;r?HNe0Kc<7us|ZMG7DkeEj1-JAV0>f5pEI%7y|!H{=HG?AH>)w&Yb_acS{AbqeM7g(jT4tdaaDrQI;eSfdsD58Wj68`@>k zfeL|2tAI`MAO^TwiHrK0S%-1rp=kU99RD4-KooYLww;1yj64TaxqWy&fIoiD{w#H_ z__M$pM4Rl{EyYFw&b2{xAyOiv-qqJ{=xEFq`)jQLmf$ULQSwtZu~{PIiV{`>A5 zAN$ddsvY>5IcCWQlq#{Gs*Cb_$50@&-EE&eS146EH<=5Hj!ygQ`HZ@$EGIi&mgO#Z zCVkqGdIBjQ!145Uduw|f(&A|fgM?TdbHVCfh|z``!}{5do6^EpcD01yTnAq`59{+!sZ1g4-IGqg~Ztta%zXTr-( zo|fyh^FXHs760UwtvFdkFwJk!WY5ziWn{3cgO*MEa*>T7dRSC&F^X&Oq^{xQK!^U7 z^`?%WmkBn20uenP6mu43(BbGdWiyg%Xen|W87GM+Hfht;ks}%m_=;{)>May(u4mUn zWHuesm^4!|X)~b52lkfwbrdfd{;2%~WxpkC(>gdp?x&mfF8`_~IMu6cv9x3(=REa= zE=J-*U#D-fQD}QMs4NR1$6jM6uaOI3mD?4{8pKH$>rh|V2cLs&(L}^LtZpq z7OLx$>7>y`^GmpA66N)`!y!lj~q3xZ$L?&G0W%u)1UI)11uDw zGuQM_|ETx6OiT&Z4e@PmZHPjgx5w3uYmPM^hhRRVkJ28Sn;Y&!_<~-)Eh1m=!8aL% zXJgXy6?LO6=wJA3zbmlF;tf0yC^=Ma2l0!IW};4AN# zEMcZ4<|-Q{9c%(k3CwK*bR3)&R2z~77IrLEJlyc%X3-VC@mURlJa4fPW5(RG&pbQ6 z=X?IO@mK%K|6OyK=Bj0I$WAUStP!MTy&R*A*NLaWv?%HR=5-<093%TA9(Gysaf-W1 zWf#2Wm^@S|e$JC!#ZGA4qJJ?RwTkdVM>lk}kX1wnn1GSa^_na?bke`u!{mj3uM4wI zz&a#r=^6{+F*lfD*V)rg$LP zFRpK(C;+k*oiLK#-UROji%syH(AfxF8eCy@>!qPRthU7^DEqTj9Mr*=z#JTB&z>L8KmWXa^OH0wWCG{Tox^ITr4Bxe+h}xFxU7u*aOhV~#H1Zt@MaB=kJ=ee2ErrHr}+$N0eZ+?G1US^l}95VGaig!fRP2(R@E;c;eB-e%x))Z(T6 zgk!@@eYQ2XaT9ObziGVb&#J$A@uJ^=p`LtRnWyz^PVKw?c*Ddu<>G{G0<^O%#1)f?SQyL{mj<6vF!`S$mJyT2HU`4Lrq9oh3TF-ctvB);)UozVp%7D)Q_QGCpp zRNnF?Dg_c#_koo3r@p8^Joh%7M7hZf}oIH7lKPp4ai8mjMIHbARQ2L`LV+H@!qo+D>a()-cV~_9n zVSgRKL*R^KZ^87=<8Ei{tzL&)+xxoqzi; zjEk2qmk!R@NMc|va2{lA`;Z;C7ev<;oRY~e70DJK;G5^rr3Qc8zV>(KH7IfYlhI{R zM8|oK@0=ndo|26}`e(l9x?;NQz>c3XH0wz_OxFWDrqs;g0MN189-&#Lc!BWDOkIX$ zMRpe-=aiQZGmM^Oqi52E4saf9Ai=55UNa!cu>=?_VG24N8)7T){0v62ZNqBB?TxPx z#_5Fr*aECoqDTjBe)s&?AxtwAZuZGqlT3PBXJFMZ~w3%V)0~PRDCQ? zUCE>)0`tI{b>vvqd5#t98t(L1r}_7j7&+CHl(l~I4 zvNqd?4}0N%f^R%vYh}&7iEmY zGgTrs%wqf!!UGzy87TD8dN|NUrOB57eTRwdz|L3+z*}?=n%j)Alz632D`CdNM$1_4 z<~XPeE#J)g^wUp`#~*)UT)cEiHnjv6{k`A*zVXN-kNRob+!v5f>|#UssGV)Gc$(^> z*!l*M#tUUO%5`xx9cS3cn77Nwu7WXzmj}*IU&tZoaYPzD*q{&b1Thd^N{zWSw7ykf z3o`=*y-r7fRrWPwR^ zGS;zZU-buXKV7sU`^r3#HkfGK$dasU8bWmEH;z(g;it_32T(d)J*9aI1j{7df8`tT zQ0fh^nE9y1r7M@m#C^2JNz>gB5*GuztCv8ls}gR+G^;+LD1bKlHo`l)m3>3Z{K ziu4{ne8f*e@4EZ0@$g&UVq1JMmY*6+h6v3Ny+naFcjXlu+tMLRN@J4>dcKQkDpmLJ zgfkhv(nM@gV>|JUzT|#F-$K9IkMDoLU-S`|{d|F# z{qgbGW1sfNC)oV5sQ0&CR~!1NIxWZ?K|IQ~++Wn0dO^o$#daT0iZPlqCoj;czz#^C z7VQ>b5y&MwE&7q!LtpSofY#r!UdpsxV~Vc3A7Pcj64n zQ$$At^)$OuI_1(1YzvXTt{X?cRG$f?Z|7JAN7*t-(c2#@$QVIpVMKgnN#`4F#u#9c z24_58f`|%YfedvrGf3Xr0VlmtoUx(tbZzt6xP0lF-}w34KluM0AN;@v$K@+mRGVcR zThv+naUR=k!w4&;Aim&@QI^!?Vh7=_wF6fbQz+$UWgS*7<4TE&<1J#wFN&0y5j^Qm zfDhH`U+yRPmpRl;*ZYp?plpSLvX`vnm6{yh%#s06RwZaHO8`fl95-b>|EDnwmO)4v z(z#!7Eb{@r=YsLY$B6*<80GESE?AYFA^mK2Lz(;sH~COFWrG$TyQ(mC0O$CdHS>9J z@Za79?*%)a1S?F6ZZ8TZpcQCTXOlNS4deU*COUZ<15JGh?-2!EU0=LR0El!ajHqlW zV_fU&)Bx|?aa#vqRu8b&L8^LnXR!}Sl40*As#y(~_*wP@qD zMSxfJc-`&!7hf3X&R=l6*(9?#y6dhx$36F)$y1K1lP?CIlTu$)x9`XRYkZqw#g3;g z`MD!_RWI57>Q}xpo_hMpv3_LTF_>Nn68-v?bg0N8_0Bs^kMH=7@6dvr4e)hONZ3Kf zP2hZDX-QO$r^c!wCT)KFE{LXLxwx8mAVXD}>4Yl#*3H-nMJ>R3n zYc^@1X_2F8!9zr&|)7Hej(uTw>StQ9hbk%nPSB z-{)^F*S5ntih0>QuN^q#4KjV0cIj`; zWqkI+kHa^X@Z-A1t~YXw8CWIfK8mxltF+^;!dTNr=D0SvsAaRu&8!nAPK?9rM^%<> zp8kpN0I$Z2hx$Z3^>>#>CvinRB+dKkUA7b6#0YABqdR3E)pz3>JhV@N4G0Ii`XPQI zWyfx#t&_b42d_?HD9 zGD1-Ymoh)%1_(dFV&13T?yLdFgDQFcrX5O;uMy7ah(^woJP#}5FBg;zV$WL&yp_{$ zB4EPe?mrf??)CM2Y~}Nx|HAm_k9>4|;@5wD96Ns0Z{s)?Vm+vS8~xFXgL(3-x~i(w z*;UJ_43&58KT14+pqU6pN9VseSoxfz{{ZGKIU^fHh7cyM)R#7ic>`tQu5zP*jQwDi zUIH#pC$PvX#ShR6xTQ{uQpWeWZGp7gQc^%?7G$`@mdlJ2s#=zqgG}zeq%t>eVBdFL zG;U&N1NFP_h?GV1#0(h;1w=sf{OcdG|Q2J}!{M4;d zD(e;v=Q7`Qo9dHNvIT9!d7r2!wvDpvGWOP0Jb>pis};^|Qh0I|=P0Hu?>w*G80XGi z7^hF48h_{S{Qt(?ci%lWH#Q%PJKq z{jGUOIq2N*2`2g12FyBKRkqY3exXor&%~jDK~A(@`=^8)xq$m7jCCWYTFR6hI{_*( z?$K3U^7@xx+lVKTVXy10vaSFF#0k`;KtctFKw~QGrLuV6h zC6s%p09u8Cj1b0U0IWPM;;e+uH%%}>%xOV3S@@xX@y(mW7dGc%SVHNrT+^2IX?pqR z`obq31NoAJrv{_E4a#S9M9=(T{?g~3*-(SpN9ioNl(9*tR^I+BWtaIk220JcogC*Z z_%Nfo$QE^CfyW(77T|~04vkmOogdG?^rHO8>y2zU*R-H}@WF>P>G9=N=tKz~OKaQ@ zO8g0TynuH(@iA#)*KIF*{D$O{Pd}xF6n9NEedyqefLQoD4)99w)Txu>(MKQA!ac9u zF>(9V8~x{k#R3z&WaJBVi4S&W0rAB-w-fZ8eCQ2NSes6Y?=2U|1X+biPsy)9>(~oI z@4$|asiYGEo}EOuDrdJ}x;;P{^Z z-kp4^vCL4(m}y{_qz)J^m2YiT(otd(w67 z+Es5H^GY%hImbpuP>C%rPYg1GK#*8U*#g~-d-s1ZQ_`Ixq#~<7+Ur^6)3%~0< z?-{4G*rjb8BjyX4G%xOBQ~AUh0(hO=o&r#0sE*^LgAHv$W1@AH-)MB(2~QoAZ(3+%fe;hLPs4<+g2qA&;Hr+FDU0{cIMeexW&ir)n`LPjU`ld#La(vJD8 z0Y9j#($|5+6ZPWN;W9_riwfZ>2oHB_O*~Ut=B-CDaNI#5H|auc+QIE=L}VxVrI9LF zzy923Jx++3D5^W-{RTMOK~M)pHHKYCr|tjO0eqq(#wV|s8hmvVL-PU1(U+`SFxjzFw7<&m3rBorz39GI%mtT5i{K@b7ljE=djlZVr%Z5J^Gn>RO)DvrEriV;4m>EQa znOZGuR(;*?DeCCdnNpWLOpc1^$)j_MM+tjv0BY(h;6)TKf0;iJPkToP!okN+=y)oc zOTenVKzOIrc0|{|Lt&5%a|t}&cm}(K-Fh2Gh7!KeFPV3UZO0ipDfDnjaOz_g6>HbI z?Q~y?0aNOjc}xq+X5ya^+&D$2v0aQU_Z9x+UvxwbM0~O!jM$)kT!3Gj;Ja^cf_K8| zCfGTh940ygaik+So+{JGTrA1Ml1`9@f>w>M+{8p`AXT|=Ay+4}EmBCu-+W}v(|VQw z4nzAAbd{(q>L^sDz3>3n7e)@*=R!@)zxuVWj;Eh}D&I=XfR-FnlAorK>W?qE zdDENTG~W5hBMM7TMqshc zr@l3Dy-{c%oa(Tev=>%WPsSZ~i927saljj<&wci@<4a%slKK1_%B3su(Z*nNbA0>z z-|L@~+Srsl8yB?!pYP-1d;IvZNq;Y30Qv|e+MCxo*&Mp91rnd^yjDH!gXo>^!tsZi z9e9w{qB#()SceS0!Ng<@lw&K9IL6Qt4?s(O0jfD)Tx;=6%-aR~NSx%K#)Ch{ibK-j zZ#(uzj?c4ijB^@KFTDKXc=4r|{N+}MwJBobi!$WV=*<&PF41F*w!Pcib~E3coOaAb z)^3cO8W(JiSxlpe&$0IBbx&!dd+Oxzv966T8?^m8>Qd_JbIR+Xsk5x7oPSDUVcwLV znh0)=eET!~1;Ac&TA^Z|e#O`jy`*-LSeV1&rkQLY4w0v6SPVKQLT=yK_HQ(wJ$HV*^!$td zLa>dEYvbyL%l^C{ztzmE!f$!|+sFM6-0uw^F4-^p$Gu`01Y+V~Y2ryLkiFUDvNJ1I6*#V6}vVbm`Cj`6d9qR9VcnV#k;>B7>A~r24L>nBur$ zmYwnOm;Q>i=EW+1Xyb%T^2|Bbv4qlRw6e$n6s;2*O`r&oqB6aqryRZ15eCY0{7Xup zvd4+C@LL37ldR8k>RwQa9fxULSy6l^pGA_f6D2_IjpxVz z=HLDI#=rZ&{$GvrT5}n!hB%kLZY&o|7xM(Vi_g~$_!n)iT=MWSZ2HU%mfO%&gmedqkKvVExdv7;cKtyW|-^jcD5?`17W4^Bn!Ni zaBXRxy~qgLKt{;H=O<-umE+TAPE# z<3@SwtTI3fJ=aEMa74aYuk{zrd^g9pow@xw^iEjW1b2hvE)PLhD=6v=P#P?gsC$GD zg3IP59ieeFIE%2-=eD6FUiTa5Dhkrk=Qbhdg%CM6U=~@VEoYT5D#gRdm%pYXUp_(t z5GtMSHl@R8)yF!T7rHMPg$tAadO_N<*qoGsm)$8Aj+69ocODhsz&M7~i!YI?&oW9r ziydUdDV}^yJ2D*7>$~C@j;+^)g`+6YCQey z(|%RDU#p`Xh)wq)?A?Fn-tovI@9-<2+l1Sy(JMYr?kQ1We&&M-ZLL1Pm|3JD@y72Q zU2b5(QEeh}e2ILI4ch|cJbY$U2B&Jl;>C;b#!(k|3)j$cDdJgICtwn-pV-|JX=aY~;OFR!rj zBzxvXzD?@%8em_|JGbM6bY6$+RR@XNSy{%3`g3@SrQ1(-)9w@)$M}@Ff_}HPvFW!c zo`2zm@yg3DkF9H)ei}HmF(&qH&cHaA9yYM_Ek?b^zHq)#r1~;HaG^uyy80MxcY~j^ zxq00`MZ=Tblc!FOyH1}T$4;J-(mY9)r2br)RNH+=V85#lRV3#)k(Yfhc8I&_@W!s| zN>7m=$yKje#)hY@$V7efDiEjE#?7F!X?{1G!73FC+Y%r;cZcQrtb#>|3);#4K zPlAoh*TzdPzBDdgyf7Yk@J-{6yYBSs)sBf|u3fq2Z^l2U&17!&rTzx$fP>g}AFO#p zN8%`)jYk*vgA*Ge-Db!u5ewsod7yPUR*-35S60!bUZ!g<(VTze$YJ^Z%J_v}`bU29 z`_$7$ox0QZOKcO+-+1gPU7w+s<(eTyZR;slj(ziaBUkXbrY^{s%CCYe#J)^ zl|^;P^fmQy6|AEP$S}tl3Cx1lMV4mKoRV*CE;^jzu^RUo{H3DATy)n<1rqg*`Ut&r zB~ExjKk?_k>BIDAV4D*LXFK>2Tk?srVokomknNgcbO7YBBOdU*Zf*KX zzw?P0>A+`fOSSEJyaFo8e_K=*8uJft-@Wq6x$(Dt;QPm){H{MfE?l~7JMOHW@9`Ut znQw?k`h40%e~ka~ojHm6J5H3lEedMrTMiGRBjeQHX@CmNMbtwTSE1zTr|KW5bXfHV zyT=&v(1{O4ozU+&g`$Ok2p~&4MU}=rx>|80&0*Wt#oSjq@R$Coe}2iJkd`lY%SIpd zE4nFyN(c+tNi8MjS@V|<#1b_26qEi5qJ%{_#tz&Hgs)MKi`s^{9DmRa8#-Lz2*h8c zVF)gBw0O#m9@9CCWT!<}LKox`SPfvjuU^(GGzTR4M)L6OP4F&Q`Ao3mI(4W(IwClA z2$Kjd;Vdx&omP-5aPkK5@GW`KlYu)o>n)%=!(Lz-`bEc|;)`z-!8-%iID_SwAi?Qy z&y4H@yX+RP>w|u1I(lM-RQA%6{LO>fddXk80NHks-ruJ(0*iO)fP4n@cH zEv$Hm#%-I^Nea3Jh!YF`C%*oqHo=eQr&MH%pEc>5F9!&_;F>lQci(x(c;9>8>(3Bx z_rMqMrCeO3cuLmY)7G^)z&4B1EXG7wi8;#cm`khWcDfvByvK-e=n|mL7ewow$44gM zmTiz%qGv)c6zpben*~-+xpfDo3ta&@x*_#@{`nWjr+)jl$CXPLy#ek?He*=v&?5Bi zyYCtw`p^f*sXOlQ-RJ1T0rg%@u#_E3>`Nz2Mpd~u!bLC6#UU-9^;w#j$f|QJ7Q9F?U5C`<+J|C_AS@2%C+bEgPo5a}oH;X2Ytwu3_({LE%EFL~<(Bkw)5CY|HLs*TI%CVR zWbE2`UwmB${DMs>?d|x3ccoox_XWN{2X1uf-*Nz-Nk*Pmx5;3Ie|W;g2?XOdbz#Fu zpYzz^rV(7Sfwkz?i30ZFGl$O1XD%zR_}Et+?kfVHbxQkD8>L2OW4pQO6~E#LlDR5; z^ab`19S?h;Oj^6kw1qG@lL zx{X*Ga`T6B6!Wu2wt^ctXyX`EB2Hvo2mBMAjU{z+8>wtI#IVsTKu*%l$0Mi{{fD2n zx}-(;ul9Y66?KQ*3x`nhr9H&IlPo?{Eq=_@iTf9{c60* z?sM1U4|#9aTnD8}n19G{4t^D^8*2V1J-1H9M>wiIvUw8FL7mrOrl93n8c-?ndjTFa z^d_WvvC%+wy3r4PLE95vmj_zxbR8+%w)?iqT_;LOTvZ_KIxYGEOvZzwf2lp#1N6pa z3A4=|u=HE{(VcS~NZ+97Q5YR7GHGx31!c&0-BQqDEz(+Zl_m5aT~TF~Fk3eBqa{_x z&YRhG%p6%A9!h2@r2YZNRs`2QsAjZ|Vk;aTR{uwgxq1=`pe`dpdDHMs_QiYU$~9dd z_KlzT2S4tcnb)pva4`{wX8`F%u6!vUkOkMYsCH*3W3ZhX>z2c>jzNh{{OH!7Yc}Dq zPsiBuS9&?oLQ_OY99Zbc1JpIXquSTL3J~+`B)fp++B9)RA2Fyp`@is{sKZ8$ zOL(mr@&Y=3x#nS+GQ0wf1LnrbC+aT(^>s^>uGF{U0t5f@iz->;WD~6%w}9f~O5a>Y z$q;GV%SyoR3GmTpB4YvSYm(|t#@7$pI_#Fey$Rk8JH8mJ5_cS8rAA473rx&J6mn9Z zV0^7j@KOL?<<(2*jP9%xeTLl_;jCW`>%l_`7CrMoi|#JNM{fZanSM&+1()fqH~IKe z?81dFdFyfto<#$8A_oLVx$QS-VW^qbG_!MRI}F&?3y%D}O{N*r0GLiVN^)e{U zSvC|SzD1PZ0RH?Jzf>F5XhU~?q9l6ZzDJw4x4-S}eu}20S0*X-gY+^jF14U$ukP4Q zZ5Vxgqct1(gZ0{}{kGm^oPqE+gm2lF@nwc8Q%CbrZk&#?Kj8p;Grqul(Dwk*P}_Yn zdJspRBTv)VM11D4&y2@D{b}D+U?Cgd#Uc?lQ!KRK{8yP$btuzKyus`xTyg^1(smF%?I`2&*!N(11N`GXm;#1PNpp!CeaB7Y@y)`= zjvdv8_oR+H$DMcGF^(KPY94&Q!Eb2GS69h(bw;|WvpA%)eJ1fHoBqe5M)v2;noiUS zDdEwRJMYphenf~7Z9|C6NjxOa*rY0K{$NDcyqP45@KL{P^3jpl)I1>>)8PwdN*yD$ zkNv4XP~hTJ{Afu3lSR=9Wj0+RI1aQ0JgR^{?_O`8Xil&?^c8@297?x6vaQ70PrFSK z&}aRo4>nL#c**isO8QaxuDpLE-JjQIY{^FVJDqtx!V{(RJCsO@E=j@VC^sFQ6+?ih z_x>hv3KmNJQwRKqpuGRFF~*U@hsU+ejq!T@UjmI+VE zxxwP^6yT2lwmy8bO5&}O6#DH2Y^!W8s^vF?hyl!mOBDDeH2EfOzpf66dYM^;{I7s% zk~7}AX5OfR9v$XVn{We%H087dZ(5B=S7^;&)(m@7@J z+wyEn25`$U5DqkLhK~^3hw~r0Xzb;j2QM}&fB`&u3L>gg>E+FVs=5C>H(^ip@RtjE zC?Q|B6e8j7c~@vHiU@RXr4 z$HsS!E7y@+tYU|1+M@J_Pr$X)@_bxv_6OXp^?pLKM7Ti!Pi+UJ%pUgeuJu*2>i(A5Y`83T3g za}*b|{2}4){iVwn#|v7_`$jD!=V0 zW;Kgk6CX_`nF9ycB%V=&A9%n)&!Ft5t2O~fsq}j@EbP%E$NV|?Gxyvx){pQRVm4|w z)s~UPUSF`SWKpm9LW~+mI@2T2F>+*;#|PR#c_FgkprFHXg(4&VD#Zva2spR5vp?1k++?(jJa4P`jz5AHQW>POq$cT9a)|>?nAk-B>}RL#`<`_u zUC>g5PG3-b-I(~&G3SuAp4+ik@(oK{E{mLu4)RK!a6*sz5Axx2FH@>RYpqT$J|$_smZ`M*lFQYV zCxAxZTZIfVfR42Kbh~||9GnNFX9W~3J36q8f$~}X2x2s{<$(P~9tLoorZYDiuwVA_ zn`Gfh_YXHdbZKXOUGxM;L8&Gv79eCZadSvslkaoicy3&~rpXzQaR%qXwS(i~2OpA~ z`?EQo;)0}~jXB3TcgOLd+CYKp(Y>OxWm_H^ z^`-B?pZpTsX7IHhcRu*gL6LeWpMOt+#4r~Q7<57uJ~ApFI8q*bCQ@c%nbLXXyHfV1}?5>`U?D3W?bk zi;03sW(hLui?a9~h6NL4Uxc8kj5a?F!&is}rk1UxJeLr#TqOGm4gJP_M>>0B&?4s5 z-~8mGH;l?!zcPq8p32A#-@w_wHm)hQ-_SUD>E##4%j(O#+MB0d(&*jkO@B!l`tmjf zDEETorH_S9+v3d!J`2y=5qIBphkr}<^qr@*hd4Nn9zCWplFwhdUQ`+rQkEMLK;ln5 z0mpb58~_?)M|f}EyohNa&b8=bQ9yms?Ras??Y^h77DHL+wltAy2RWaR`^%w;7l7%xbkNKu-IVUiz6* z{tWcn#g|02?VYfKrx6_6G60a(pBJ_QW1F@Ej23@syCpC781tP65);bwS^1R0jQ6=f zc*;#%LUj$AyD~d@RW6?C+EI}Bhi~SNPVi`&*by{S;z!^1q8<#q=prwa!&-W08}J4P zw2buz5#C}etRbpE3af;owh>q@L?f@*T)Ped+Ty)DL)vOJscV5RtU+{t#pZkw=84Yd%Xu>aX?H7YP zqiq5BBOjrQ1euFT3^MvjfhuFzDD-$~ghic`3ouA@nbm}WT6!!CI2Pu;*|Sf?h%5uq z3mAB95;6Fb1q@}!O&c*0`p@Obsr^W!t0`HUA}3WEnLPoVjtl}%k3 zSm^WmC%>op-uJ$D@Wotd7qoIp9k`q3->97ce7R)4_!XRyg2?B9zJ%5#9#7ctlGjmj z?+xo5u&f<3s*dU|xU5PKFV z^HSz`P#>e|XBD3%?`uGF*h+OHa4wUo;3nRoZ^BO+!je~_VNIX6i1{k9ZwNP{YUn!f zL_6Q4%@Z_uU?Z-6-CH5!M#8htd}BQI)RW`ftLOar-2-cf<+>JY>d&;VILDgw99~YMU;_;%vTq-MO_SHVX zF8$JhBI|`uMEW2XYllH6v&c4m*c*9axbcR(`Kn%##}89nX72D!26Pz{r&)~Trd!$O zCWYUU5P9mafbujo4MPdPb+Vp9M5gK%toW5HU!qL5#oKtt#Wa8@hb!SyE^bl~o60UI z)wRO)CC;=Hyeff1FBJ6Js~VqngEtgRD^=79NpFVKH*aitj-|{OTQQISzUGe~{n3w& z$NuosmYanP>}BAKKB8w2oXeDd~W2nZ&gLR9r6ot4Q-SP~^Jj zwF9b+n|<69_R#Z&VVA5ePWWYPocb)FELy06gmsAtG-j?pT7+HE-zFyuhGo2*Z<)$l z5Ua?-2Ja$v1~Raw6nx2pTRvqBSMsIW;Dr8!q1L1%4+Ap)z%;D^1?E&fGLbXI#Y8H+ zeK2qA%mZ*HC7170!RLMc{O`4E*T&!Z&;Is!^wCGh<*V8Ri-}(qXlaD7WqS{%b>xl#CQ2fBL?oyeG?0Lg<+XH;fM(kbGN1ZbW# z?kxdgn<;tASZDIdiNOxLu-4 zZ>@gu#TUjEO~kAru4_}uZ}PtBzWc@&3wijZxa-lr$3kdqf{6;7v(S>TfxB?w()hF% zU0ekCA}lrzUMS0MShJZpapKtczz5zx4jnu+w#`sBaN08rDU%jx`QZg`d?+WCDH*36 ztp{j4&?(UP=G8IT8qX0dHF0P!xnGa0(-NWPtygVi3i!=CUSzcHC z>Q}yE9yV=EfH0w&pJO4;ANIW? zq<}XXc-rXS*ybjeHnF@-V!PN^2Ge{?E>9+ksb6na|*n(|LLzHpW&Qj6E!|@j+e;j<*>&YSydy zD72Z!5w1RAo1|=H$QY-1ASyTP7dr4sGQ^(Sst8kGGSP#4#yNVVHkq*GL|s%5FCdh1 zgAsCX)}jYGeFNj*l~{*P-B)ZxDRozj5T|aY77G~HjYXVFxw)yleDd54vU!B-ex0_I z8p)vxy>8{Y#<*@}#46;MdF`7O7{Bee45&x!vUuhTzV5u^ls3BX>cAI;`T#!SgXM4f z8=vW)pZ)yj#>YPPcD50eIr2Q!FAzy z17NP{gnvNlGMAEf|L8tPAlbMQG+a^LXeyf~HV7_YinW21_=s6J|8+mKycANeG&BO% z33x-i2Q2mXg1Z69$#&U{u|T7o*Rhnn6X4|vgMLqGrJi?i$HB;6&V=PXxz)n5rfLEmAaGoZZoOSNzk!&Y!8a=~Tm)IT`aTkNadrHmUok1Qeor1ATx z-qqkEzIWRQvY-W)@m~e_-9Ox)cGCl`r*-4WoOhf7>Ym&VK<~26SMB5;^A6jnbO5BW zE)Mg8MTuh)Yt(_)5jU=09KZ1!zcF5Z<-FplO&Bq&1szWew>GxNnKNg`AN%8f+^^I2 zw`^xIvVUx|85X-2ytvc#GQ_{e;Io~=3&&7^n~s0Qgfbs9Vm7xb3tMQb3pBO&t3Ou z<9p9Ie(cydaq_hN+@_yPt>b~KRY5kk-sqF}88$q2M##n%$f)lgSNmmLP*lEyCc4{K zIBqa?Y&cspjVU2Ms|vz8gl41azM!(d_=+f2H{ta+8YhdOg|D?(VdDVFQbOgYIGAs= zSe62G(x2zWp<<>(lyoZPxgpm$zJ(gieg(bwa{~wc(xuHB8@a=W*Bo1ZF3ms9BX!u~ zW*@I1(w=b{t2#p`Yn)ED2O^6Lddb8D53#FwRSjl&>eS;KBiuy9H|g@VfLH67>&5C- zlba2?cu|R>g5Q83AYGGx*qPdm)FX@ol4shUQ=D zY>4h9P|wN=OhvRaWv|^dsO_wOL0{VHK4_|N=}V$j`!2y<&VLcN8WXzEb(bD7=L^LE zB!F3A^Q}PprL=8KGSCF{cdKn)aAxKx`^E|^;(=4Pba;N-8*WwKD3oOc%Pzd=bZk*e zxtg|IU2TWg1qqAaztgVyhgX{!V|*#rpa0jsXZ*+ix4%5DZft67Zpa)rt!3La;jn{- z*bfdm@mc}=ES%;2uao0bpvol9+;|HAqzk{y#9TsbXK)Oh;n0bB!)3`R7(I@xYhqR+ zR*HrwH#iGh;p_(!nsJ$j@(~ey38ek?M}24zWb9@svfYIdf%~gtW-gR~)W1A+mTQMH zTqng~R?Y3P0gvVl#F+0bhncD)_7OmjrpDAABlOAAbqg?W%UeON4T+#!uxu3gnjwWy z7{QTIU*{U4eEd($u)W*_BXRpl@NSr&1iPp}C0efoFzA>%8b>tH2rPD-cc+Cf6Oubq zGCHYgl=l-3Z~z&LMn2`zr94@8WIBj1^wn_|3y@+KE_w?iQ~c3CB*z8nHF%Tb5E3C1 zEL|x8lErU##3g-iUdIMo>D5BVf5!!|6Unz;{-%p_0n&2`QuL&TAe5p?J`fe+Z+9rk zcJ8oJtO0Jj6p_o|=4lj*T3+E?W0AO@-{h^&W|nnc3!T1%Y3qici~;Cmv#_O&E?@pY z>+@9X%C)P0{cf9|QPQG|ClYMVHncH|UKU&0I3GDO-uK@3`jt>NaqcU!86NT~b=+vr z1%Pths1NA`5I7>g0_JZ$-8VRv0A4&EAb`s5`%B)X?%7wsV)$%hfat%I5BI;RW;wX?1=z5(_9@9a8wo z+7D$a5nVNqe!udHJ)VR?aNR8!n8p>P{pwfOw2?hD-Mk^j+v-omiKky&)V!#c5}F@- z0GALp4CgPrI-Yv+nepti&yA~BulN;GHpMq@@NJ&r<4Ldd<}=u|8Jor|TuPB3PtXX> zk)y}Po!b09@Zdw1HmvO$f|OkU@yftK1p?skg!N zq%^sV-^z>MRN<{-f-H=x3TEofE#R=BU$kIpBYGN7&JXyf%FK=d@p)QMs=i9Rd^n2cn;Is6eFU5QL@>PG9{!qOp4J1B_2V=$+R9-00!)8)F&B7^o_a!X% zd?Z|`0y~T<^sy)s0-SwK-c=;UbNaaR=%OZ+g`oY|6e{nhY>EYfk)_rMvB^hk^+g?r z*Vo6{vuDT8|NPI7AN%ni8<#F!94FNOc>Nw9{mLbqV2Q_28Q!Vy!U zQypQ@iBA+4yj_NI+0PQY)`4Jb0qCN&(ARpS2wqq-wo>OFJHn&axajdZr=fi4Jaupu z#fA1BtFLq7o$B2T2J#%-DC#^%d{_as4);_#zi0MQdG+<0MqBwTT)cAg7x}_{Nx|ci}@A1f=u}@+eVBdOUpfhbfHaCRxSA z$biYnB3C-OX7oqsn3DUgBg+=D*Q4o14zBb09d~r)I>Xuva9yR}`joF?{7Z?Wi`u zAh_;$Qv;D0*D?ZV-D8v{t2{*}pJHtmXweISlq}5R)gPT_24N<_Sx4(NXW?=J@F7Sr z-ng0u_slax-ue}0%n@L_H4-v1pR@axxXSaRpi)_lfaZsKFRN%Q9c8z68rG?8?P z?>q{dw!{f2x*e3ba;3|CUd}5qiziKT9Drgd9&KdHmKt|E=-DOE3CW=REyM-|**3)kc5pJHKpk!C#=<`rC2{`_tL?HNR(q>G z?32o=598N}^2KgdUS3+ZkOJ`OSHg!S38#W3JvLl2Z}dQ`6yCDiU|mH9+}~|ibq4Qx zE7Piq5jnd{pVPsO82I??v;9^;cte4H#?K0Q%vdk-*)Y)O;o*td<6nPV{qv?aNr$uf z5-Q&$P;wkQi`th|ZSIw8tTr+m1ObXcivLW-6 zU7OMg|GaRHjW}+!5cmdN1nEk@QC|G+^E&)9Om2sLG;!tBpiRshGQAh};T zr*p~q+=f(Wde1BH8K>fsxB0-L*QNHS_4LVtAXi&w#dio1op@XakCX8Ej6b%6x)L&^ z{liK;jfyVi+eg#z!~H(U*deD=$ycV%_#NI!%?@Y@^q9v6(F`uqt}hI6QqXY*%$cmA z%I5E~KxOnWj?l};m#$sCHvazK`=Rlchu`9d1>68+Zp|0@p;Ln&uuqZC6G@O7&CDyF zCyQp&%0t%K@m9Q$u4)+vBU7;DK~pd5iho!Qr9e2u49s`r(M3}EiN|yyM4$}aMUi|q z!UcodaH+6}_6eGlL{?y&GvZn(v3T0dexRzzh%h@+ub$VlZUah-@Rm+N@}ArUW_Eqh z)1T9IM9UYiOVuV-@_7cZp{#)GE08X?2P{gQ)!~O1=r5Xil;MoWE&@u)Gq2O2ZOJ$3 z34#FD+rJaM8}@u1+HG3cUBo4HOBqUtfIH0Op?A!ip3dfuZMunqbb@sFLKlnWb`Hmq zb)vN0nC68#16Yi`MhF90IOLWt`$SrPw0^)U%+ugrpX>xMm%t8M4`Qq5k4b5Pn;`?U z7blb>0}kE{KqFbiC@~I%|D~I{LGd8Q4tVZ>F@RbxBE$xJ;I$AGZ|WHx*RO90&ns|i zLP}SN!qmiz@xu8xFpFlKfCU_r&SQ^#cAPu+il0zgUI&~k+Sp()Sb6pN{qKMOICkQM zHs0A7r`>cY7S?FF)Pb@W$kJhRR!F8|VGwB*P+p?eL-T zr~lM{XFTwx2mBkK0CAyxh->U-gXaZ_z?)&NezuQMD-_Irx@5Av?7k{IbS`koSUUcQ z7@njJ)qG0L8KfYa&$c(q5Q$k_wvktkcrnRa7gi<1O>FNWuq(z*ZFurJGVPuPdsw9t zS*7|1B{KbjOnzsXjoOn>JvknK{Hwlc!$yKvqIqSOHgbPgJYDrTq&Tt>lwZ6hA+6Wd z9&9}BzVmKvIL?eSXYL($+;Lj`8cUM(Mgx~PB;Okabl4XFb9Pc0a3rP`1G1#eFR*+O zh-2DW9^tHfcc=~N=b2lSS6?Hpb_Nn5vEKLz5OZFOW)sAlAMkEo-yEA8+uHDMjtdtr zjLmBsn(eHOd! zU(#m&UZB82ia7j~DXP6(TghlCU^F-0-t*q~s!i_nn=G{7+Mz=*<*+@3>g1yA;VoJCw~3c$A9s|AMtPf@>b2AcW48A^r&OM;ol*R40?%^+rnvEv^j(8 zTk*kXXH5ua+NB@_XQN@FtU%gUFe~$TSOLU=r3&n;%|4K$!GKJ_ZB~F-+BxzDXLX|E z?EuC+fd08IIyI}2WC}sKAol zz~0un3&_t70?V67=mg4s>CT0zJn#u^$!9ZavTrt;UU=f-=%E9A1e8fJvyuLUatr|x zY@3Yp;e|>{J#(#&ezQ4g4QFO7J5{bfXU$ zrPasHYG<7R13Gf>;(D0g{2~LN*6`2mIX63qX z76Lur#h#j9#B@h>ck!-VJQK>{x()e*o;jzxX| zi9oy(2EATv2(;L>V=B4hi-iGayYxbJ&bXj_4a~#^WcT>lLVz+lrx783c~*W!qUrc6 zuCAvbX5v$hEEKa~E`NkJbrB=ShI7%GU|c5`IE&6;gCC;;2EBc?4AGN}ie5yQ4?JaL zu}FT3x8$=}Yd~M=E&YCVPPor~_VeR~7hcd}GZT8br|LshUTwev`Q7h(-#D$sX}&FY zj$Ln-_-A7BlReSdJYV-~*oQ?+eW?88zvc0F=_e4qOB+$H!$oxUfxM8gy6Q7N{Q!c> zpx~>vaC`ab5;WSaFJ=`t#kSiGNShH4+DGzgCt45LU;p)g;wQjt)M)RxsSU6;AV-cL z8-M!G{Hby8z4!X}fYWYfaDVaZMrh&!Da)L@4H+-)KQ55RUzY?GXY11;U+r#Hl{|}a zKj8uI3x<5BkMg(RHC@n6WY7l2<6D2)o=-eL`m}ro>G~2g*^*Ld_Hn5bHeWSjk8fh` zw-Nx06gcMa3CYFe;K4P&=KuH;kB=w5_JlWbye>;0Vl;UFEB|=q_Ml|_^cFp$5=Zp$ z+tpjzP_1dfa_^Zl-u%Al{s+gABmDO27M#*VI{;E#4!L@zk2r5`Z;nF;4?Cs+u5v?U z-*tSZUw{ZceNRzAml4EFd4J<`V(SZbU&Lub+KRTM+-G8oo}z<8U0mSCNxprZ4dbg9 zUL6;7y!z^^7?K|V*(rGbxaG;!eQLL!wy|V+ouj`gNYY;+ie+@1-@D5r}!@Azz2A- zP5T;qV;oexd5ebF|IVjAHGb^Jer){aC;z!O_@}i2KE$`jtAUt9P~&ea=c%(ps@lsX zk7cXI59LU!>^kJ%_B-Y~q1(ecRsjB;xS4+?&r$NkoHm+n7_ab$bqO;LJ%#9`P)mqT za(JTvin#{ zWKdkb@~@NgE~M{Iyy%NeC1!PBpT-HifzBlsJmK^Fv$*lx zZFTnSIp4(otN-bLIxbz!O>BO%8(zMYF>`iZ&#W2@OFHpXD18E0e&v4Nis3Wn%4;Z<& zTC0v&$eLT+B;dVfsk~ExXo$JEaKakQjBQeEsYJf6lQAcq2k0y4!L#y9EcQ#hxq*y& z@zM?|IEJF3g6;-y*6_$j(te>CWk?-@U^vB|+K4qmoN`>V9+LO; z5&gl3Pq$x(-VNX4CO9GOjx+;}xCH1+-l9(pyV@S^Ok`yDR$!hbU1hZUB=icc!S;k- zrZwStjp#`nz9g+In}jZ#k-`F&^+m^|pkT=l?`k|U7*%q@seQ*U23W8_4?OeWx6)bz zO)zP2rBZUdq|3v=q8eC=fd_^sN&ZU_6B~m`zT$1L7P1_9KHGcw^5uNd%9?ychg5q3 zg{?*WdFt}TFMoMF_4L#E%w5Gf?xjC~+0?}U;DZm0_h=K$lRWHPxqN9HJ$BUkJom}W zmKNLIpePo-fnvja@BmLo#WO_!f6Eu8%0PSraI5x3zI9Pnic@>)m2LT#g#dh!amXHPAQ>VwD{?mVYoIZV8n-MOavC#`g zo;LzZDJU5;m*< zFj_4q8DL}UnsxF`y?z=8UUavW>Xbzra)N!@sBF;>_RDA5KkXPQ^}~kpR)LR+4facI zSYtW>k{~N~bOX1Q^z*q;#y96rd z%T>b^C-Oc=3~-%XN}6$5yvWH{lsWGw<#53#oEMhx>g?vJILkrLqoo6|PL3+?gjf&Q z7P?5w{%b+=F9C_%Sc+Y!?aSg{+<8vzdf#8ykbB24SLo!yp3dTA>ACVS7PS5S7aix>pMA=UAA|}ZplM#3OD-n z7hdMJ)ZcSk=>go|(E}27!Xe|F`4-H~Tl7arjqdqQN5{|d4lEfM!<-o>tCD@(rSlx5 zKi8idz2ZS1y^6S^(=^ifJ;lgsStmrduN<~391b|RFcO1YzZ^48H~`t+K#yp6%>>cc zE~`(`@=^R6fUJ}9*C)azTj+<@XK>h8DdT9r`;V`go+ky=zx-Y1ThHxH@NQVy1k><9 zPfE9jrqdyli%3Vm!9A-E7Efu&2J(4DlY$hb*9cHbUa3(u`7FP@hypaf`;t(u12m;U z%^fGQ;Um)~BO5*-;>jzgeEDsG-~!9~HV)-LmjUt&)GRv9qs3fa>ktB8+*@ZI)16Eg zdjb@|vdCDDcz_aEgHEoiveSaC>JGbO;`$L6CI)O35g947v@+;5iM)lg@#Kj^48#r+ zd4d%=o(w(l^(V)dzx);P9uziyhE-a{MlAR()qC$gGwy%zO=JD&5no{VLI}Qyh%Ybd z&GkIsCE89I?5y=IAu`?aWMSZ_@-7g~7pNsY@d!XC)v49sj8pIpij#Cqo8XBdWk=K# zuiC%<`ZLYh#1SL)6-+yh2gYxI^0ySnFV<_DdFA(%HokxE&;7Y^{P^*)p$!WcCpO9X z95oxWgT84%ebAZL;D?_U^Q9d5nG^iSpZ1SFs>FaCI9Mj+)E*PAL{ne!_JWdXpjvA3#6>cU5S^LE7k@z6sLjW>VWL*wMBQ`}p~ zmtYBxeP0v-U)(w3Gq;%X)RGwFa>gm69H1RQV3)qYCQdrh%K{~;LRKd7wOA0&qEP5W zAk0CVkq6{QU9b=GdhJ$KF<-t*_r`**xIH#Td`?e~{Q@hY_2pEf35)knL& z_-xxXHTWh4ey~~rFC=(AqeNRI=J=iZx{fdi;;K&AAV(SH!lmE(KRT2{eyS>BR>0gg zG+%KusJ;|Qd~EdD1iQ_M5$!6xe*@Dj=%PNIM{nwx1u#ZPVWv%j^D;*Xkm2ow!$%H}mtHwLe&HYf!uZ(7K03~- z-R?beulleS&}-u12BCarQAJOq*`p3a)HnVTaI%!_wej-SF(ZCyGqCIrZmJe$(Sh#< zDhMo!#1ZudZh9 z2bRM>@wiBbOy79Q~Asata^fn>5}QrAi81m;L~qNyzYj$7sk6PR49O`RWu0t#h_d9o%+Ufd<*JTY&u*ZgMT{ z)4xw^jTXR`G9>bcD0@zCKpryAD&w{;oqm{8e}>6clBo~LH_vS)%TIYas_;uM?Tili zy`B|5eF{4KR)$IeI+|t$zPT1MG|ur$X44%UXDp@R7(Kb+VvK$RmIEvd2;o& zKC!Z`zM9rS5~==_W~WF(T&L2qI*QeKRE^MXKt175N;JPobRX?pQ2bYtHekNRsH zr2J)Y&H%p`XryB8Z%ej1L+9FVWTrZp&H;|20ea(h@=_n^61q2&aVvDcin=3SjxBk~ z)tc2TVs_rcKxLK%l);e8IUHF;BTSt!*glHniZL|oNbHHv-z;lKn=` zOqoS8n+$$V<};uFZ0V6lt_%EdB9&K2-}UIDVWYc%ZsqBEajU|LPVChQZL)rksKs~>nqVNu1Xf70cZ+zXSN`_jxUH5Sl zKunH-1SVc&nc#)xW`*+ne(ZiVc3$}=p8Li*Epqu%v2AT&Y05+EhsKA$^TXNz=d;t; z%J167E_FsXe(d8;GKzF?^MX6vygr_ZHSvhQ)EU4wI*{i^4Rm3xS4bV+2o-mS%Jqe@ z!0P0zeE@G8^fgmmf9FC{+m}2x0LaP`H+*aTyavXC99_hwFT8-;T0DLdtG?uKA4i9H z_&h7$NPgj>HouQOHlBX+$#Lk=VQnIgs0mn%q<%NA^OIl)Tt_dsdEE@Z@KNz&lgrx( z4?Otbc=Maz?5By@6sKRICqEbFk`4q(bK~cJ_UFcha~HUF5tc{JUSZp zT7Vlcz7gJALECKT8;k*R@)w-jE zls!vHR($BBY<<=o-p0Xc_SkjcjTaIg#m1j0hEagN?gQ2hE~J3u6YG`$nxnY&k4C@F zjxGB|9g;U4C62YqI~xz%q@qn$hl9fF2wK7kvHjzt2S z#p!USntvC7i?~3GC6`-AI!14Pyl|&;lz=<3b<&Bl@LR&9)}WFR(UH*u&`FU+4+s7x zpZaj5*Lwo6y#_`KD=a4M4ANXE^d}vBsmIO9E$n4Ltf;WfMr4wq$i`}#s2vAWMTd<| z0`Y(j!Y&B#S(b#l!DQodJ&~|?K$c0tGmx?(0Bzhd%US4`5zlC4SZ_pSak$4vJ03HD1D_ zoOv_(f`dvveIY44Dp=~ZApMn`YHyhqoigT&9oiEXE~G?VQi}_*CtOO3$<6KS{^F`b z>qmrRVT-K%Q~3QPSh~^0H*gdA!-o&~sV?8z$_9idk@Rn3!C_|UMxHj#x9bWCpZ?It zW{ECroZY5H-2qgVJ?ki-uo54LDOcCA`c)9Zx~W9*s!X5ciT1<}&Su2}-@>q6=0ap! z9MGZ*nA#8UkHDucUTjl2)san{KYvOerH)eS-?|keywRalZNitaUA}aAeEo?h$KzlB zn!kvIr^Ni^5wFV+JI}F8vz4Dhp>UxUdPw z7?lBH1`=CJnAcr@AGj#G2=Fl9M3xJ7bb+@X0dgHHD}=6`{ctRJdj^{}gz%hNC}r$< z%vd^je8VPB?;n2ntyaMol@Ui?^NvmUql2WX=QhiY8~l(rLV`CBVu10op-rxDR_Jiu zQRT}B3zEd@!i9_Dv?|U;3r-Ge7(B@wLYv zAE!>77$;90^Nk+BdH`>@)kkntzW9|w)8w1%HMo|88m6~)GslnLN15f(d z%s=6jcRNiqjwtJTm&h9fbh+=%`L=0wf)u4!^`AC&0+Uy4p=YKt26SHKY3J0*GRIR! zj(G-+9P^yBi~-PbSVFg{V-CIQ1FvJA5`l9r{m0oAXswWzcELA$=M!plFBHMQ;#+LD z2auw&;w=cyTNdlinoV@`p*^yqg7 zg+W-_tYNm(^)wab;%B|!`iiGH%^*G0(LLPaqIxdonhH&a2_&W8dg8Dtr7ZZ@2fHs` zQkvc3DicS#pkssE`eTkVGh5n|A4*NhJDEj2fPM~wn7Z$_RL3Om8 zQvP~@6+o|&J@le4gUSs4=L9NuyI5p&eIYUkh!aJfT?Y!tcWgj#u$U3fz9~D^x9I_L zSsX5X1~eEEH9k)g;ASI4AGb~UkUR6}EuWP#fskoyDQJ1cYt33Xxqcdfk&=G-<+y3^ zhab@3^3w(IiAe-hrdpC?19n{-y5IY~-}4<#KZU_RO_n?zre3_}!_zcA&-%d+eqbC~ z=V^>$BZb@kJg~;MnCs&ZJ2q?}i7j*{N6`};^8w+lf}km-spvC<#o=gJ=HkI5*?rWM_zOSaqXqR;qqy@U#^{z0;|rl|H6= zp;7id_QZ4L>ZS4g^UwQpXV1U%qQ@9M`n7P?5i_)n$62|XSjIOX7yRIL@{>rq2{*3H zL+s!&AAWL%MNFn^8F7%gBz1%<)l<~uKe6mP-j?)#>KaI$5jI|Q*AycK?W5ykR_>HX zC+)!t5q!S;_=)4={qO&P>wrlgEN40`R$!l8=+{%00uGzI z`|LQRzRZmoj;D@xS~_e`)-s|Hc1&T)1*2{m<-aC-~>O)^&oj z#!Np%;%DG6SEpUDb8PI2xkH6sK@p=@8RD(H*BCB>oB=$3EmgXXC71c89S~mnU77@_ zi`Z0e*H!xBhmek24$oO+g+@N>Ky15&nQ|S5vWX9%46|_B1G|)oH+2(l_YwW$Jb%<} z6-;z4oAA;Lcf}5fjc&Ks0Qj)!tn#JKeMI_6y}2!jPvND`juwhk&F%brMx@GWRsHx1j#pklCdpNA~-J%=84`;m-V%r7hRO%w|gA4)@L7? zh`={46G9-irorn+s5L0ej(&J4w0y%-XM>ekmtD{am-5-f#0y)OE?(9`e@%;Ee%Dv_ zEi0NQVgBVF|R1urrO9)i$&+)w?Fw7QpX5>xODP`TcuAw z_J`x_*|THcnrMi7Qa6|BEIN7e^qqhFJN>gATN|6Ep$oe##q%8OOUOyD4< zX90XMQ1>zWuftDZu~mJR_(WPb(};}`0>uoS94w6ChG;qT!pI>6Inky#8J)bx0dqwu zW{lJju_$whc|~?r_)N|;rUcHHE**WB*q77dX}{b@sS1je#~e+bB8~S6|<`numkz+Uis!R z5xb(sZkb9R9>)ECZT7duOE0`Io_^+;@%#(VjceDgj`j5;{)S{;b9UPZ_}1y0ye90n zicVhxN;PGVeRBtpCzjW5^3Bj&_Kll7v=z<8VLyrIem0uQQwL~nooZtpl>D<%nj8I8 zTeOZRH$(b{2%lf~+@L>v^%rEpr-PVLXXY($sF~wjy_@6oop(B}SJnRbdFLH>j7QX# zht}7bMqE#RDu|zE>-gFr;CL`!rsxzL1>06i+kux|H@k4|KhCDD9McE~i>!pEjkCCW zjN#)|`2!7~5aZS6HO2eWfB1*vM}GK6#;<+i6P`Ekxa$u0SLCcy%;=#Wl&dy|SjTsK z!ivgVyZDnW+J&`XB;udJddcWic}wFMcu=t0Sn3dRfFOfXn%Pz*|Le~LcoHj)+?Z(nkjuVP5D+7_6Cx27V3JdQ$!^_c zx1srr+d)G(t;8{DuM}9(UPt>~!QCZGej(R3ciJu>eu2>4X5irMI6KkFgaxRG|GWEu z+MsOVtFPoU%PvSSZtcz3Y0*Snm=Vy@u|M-B?{-jr=~rO2oH}V7rT7M+xtCJ$e5Za& z_^_e1&!vkO$M^ru|IheiANtU^c$J@(lmCh}y(6LOwER*b{_Chsu=7em?`3gr%RtB6 zeGoaF5-(#tk9LtU1>?hA*bCq$!|HbNE?Adqpf(X+1B(I^~l~Otu=sL zf|qP!Je55nLeC;H#XJ!XVAtP_i!DD1ViJjsjxDb}UcPd1JonslbIi zPI2(ylseG~90ljy7v%FK%%XhZukE6wiX4)0T@^#mS!Pkjo8Xjb(rne}^PRUI@RN<< z0bV(#ZYr~Q>kT`Qc7m=lz7i{!Rd?R5Q2x3%qu{D7C5JX*lMR~msQ){UZUO2J^6Itz z__DN@Up}ji@3Z6O7hm$mA3cW-X=7e`_cOL68-FBBgDQXM@Y=Ysb)(`cy*hb8U@9q| zkYqlAhm9*&UC$eZ%a^SwC8o*{H}YNhYrXS&*Ra>x zdw=`GEMYm40ZO=#KA_2OrGB1y2C)_#{Hf zB`-eLrN$wo(lgh0hV%o$(!NnuZoE=|-3p3vigg9r?M_B~_GTM9ZddS&@v|9xfr|lL zZJqj)4}a`-{lP*DZ-9PY<;g_JI+s2&skFbPcMA~5&0wKqe<+xB#TM<8vK>-ekutv> zI(%fTX-@l%&wNJbnZ14^H1iQ~md;z4XWsB2&_83K`w7r>S>njS?y0?irt5L!L?6ER zg}nduL3~<|+9Ws%2r*CO+|cdSkf-uk=R_7;_|;|G#ZJ@FD{yPbhq?-vW99lR>v{N;W;cDIZ4{I!#mTsGoW8Ukwi4{4_rQ^4*(c@B(u0 z+zH+az7w1`KmIVWQ9~=T?uPCy1U#M9i#y76O!qSJRYThZD0i$ZqS9E(x^Ka-=u~d} z$VOK>Uj}59f$pp7!I+uPAo5}PmWdBw^#NX!ar^3e(2uP%z944uayHRXOM!(ir1+MO z&m)r9^1`H*m{&>V(YAz88=%s4k&iA06|wal54dI1X!+_zp+)$#gI0i!SsVd>OmMIY0VML6iPY$s^)Mup%AN5r7w;O2&EU zDp`*+Zqv=+KHykVDE-JNHOl(%8&vcn(-#t&Hvo4}yvS@!3kBXNd|LI}y@xyI<)IDe z!z@B7&)s=8ZT_j9<;f+%HLJ%LByeC*2q;CJebxfj8$tz?#Vj)6;v_;Hl*MoQkgJU@ zz=TRv2iq!|^3wu0n5qLjNgZS1mJ3wC?SMa3C&%6PWdjk)veOIBHrbFWrw-Jh$Dt@T zpBJ>ruNr6Q=J8fGJC8j2uz&COr1~jj#t!z`2y0nkpXtAtX49weyMBJOR{~dDapkz_ zrkk{ZI@_Bh-lmOpKN*2TI*2vx#X=5XjJOKK%rU?(7)7VT%J$tZqS!#*3npi2obB{DeetE2Jf5F>_PO!;>xW!d9__^sblD!RD31vbN0bR^ z6XJ`{G3cyP=-`VBWXi~)(4f=~R$H+#!;bhi6i*Jeq{#86Q#N*cwFy0Y|2dj>_K*Gh zb*Q|1&u+;uS4o%u@dKUKYQ3(6=QQ#{OJ^4Um{+A7d&5FN%!~+$n?{;82<}2SAd(KPdEcH*HQ{|8T=qv6%l8HXiXpBTa zLEJcJkWbPVzmkVlA2sJpAi2hD*Pf_cf~jTq-v+j|wbZ$Z)+Mv3Z5$_k^l#tNl++~A z*aXtWxUk!WLSe_}b!Z z#20ue6b?YN=7!84!J*UqLZlxA2i>f~`IMo&W#M6dc3(2H{^E(7nfXsPqw zq%TEsg3@b#2CB&zba0j5#J>c|iqrBbB1c(=#8bOMz^eokfG<>AKJDZp1g%G=i`XSY zv_W0-&Wo|OK)w^~PVg3>K=vfN0*xTZbY2%b#+#Yl!`vt=8r|5!rR^o#C$DLO5x_Hb zxO7w>EBJ!KO`X)`qRpAWcJeDgr{`qAVw*nI{tD8g4BM$_K78;Nxx_pe$Ri^jQOsk0 zFwSc?g0GRdb<62*np$VrC*>F~(+JS3?Iz9ud@%o=|1 zy^)1A7fnibvu;Dttfyj%V*033+fY99UFy4`lbYYqtP+cB7S-IrGRT%S+HZ=Y?OYpg zy#CsF{He#sHP>A04FNA%0?^N0Nj7c(ZD%9+Y@gB}bL9}9g5zY(!V@NvJmzEp%VuLi zKTJMQvA`%e)vFip){D>PhfX>AOiwl`;J^sP*=1LZlPYr&ND)pQRGEwkIbo*+)K&SEGQKFYkqJ(p9piNN z3KeaV{_fDiM?J(t-t8i?)x(bvZ6*UeC4nwpp7z``&yFXae0;q8%F9C0zZq+A=H!l> z>F3BN5A?+r_gXenFu)5AqXIbcb%+$Yy($>yMGqGd@Hsy}A-ZCVk34$K&zVpqhCfiijq)KXCdRP$YpccUcQ$FUNZbBvg!pyXU1zEnZIc#+DsdD zp?G;47cX9Z<+bt8{@L%2-}#;28Baa+wEFs2vxto;d^H0$9hxGRoU`il9|?pFwUD9XaPj^3+~F0H~av zMo`(!s7y%~!Z{<|<+{+es#NX=t^V!#P)A09w|2@=v-pN>uQQafkMuu~1;&;Be=EQi zb6x35993VNp6wZetU>^Pz3FuD5)d>^7ti2tIczC~4xq_)oe5&Ls|Q?jtx{{rXaBRJd(gOWu(=_eS4Ol&E;eid*$ z_c@iK=!m~_CwMDp6MQ%k{Q)p_GDD}5bAwdb`AxbY8OK4_2a@kE_WLAUojy<*8ki2^ zJdB{kXPrS$u-UfCumSGO1`T7O zCY#BC{^&8IkNI4PLh!^9zSFs5%VQ)<5$R)r$#>`AM<0u#=bz)JP+rj@3CA@T=-9os zYg~Ti6^hcuHoVy+voX=;knb(>olfX>W2#iy#z*1oWAI4}B$Ne6Ppr_x z1(-7gC6Q~M#s^mQVv@yG-~H=4@R7|1ckBo2M_pR}Y zHp1tfd;a+J?Vr|0VSgsJX`B#qL?y?c)G$oUqCDwYY#kTUx zL+Df3)X?5_)|w(ovyx&{y}FS0qT@wh;psb0+Zvog`N){2F4n-+7O9A=@(xz%$!5SoE4gP2luXRO*eFD4Sv1-cj=x-VW1=ILQ!L%(r^-=D*(Das{xdZ9D z!Y>FBrT(k>+h!yJlAp3zSq0=qSMnQtl0ZC?x~5h@ms$7vBA-Q4?t) z&`G0^nX@|hRC!U~U}m0~qOuUKmh#r=G1&2BP-IBDL%=sry92+mb@Z$J~fB)}~+itye965T-zotPOV1$1uH&jd?PCLfl>8t2Tl-F}u)p5jz@m6*d=tD7u)kwlx4ly>fBMez49{w(Ey(ePXUJv^IbHLk{J%6r?`&C$oU2~zI z(^KgDPVhUM;LR|7C-_Xz5v!0UrNi*ABYhRDN3HVn!YVj{=#$(+BVt)hC}U-Gq@0|W zS5o2SKa(D1jAqcFZyp2!rR0`(Z`*GG*I0Z^KEmTX97=JSc`YSjHT39s)}>)rDaUE= zPL-!9PAB%o8If4!cj+Wvddm-iQc@d=G))C zZ@lrwYY5sG?iza|qB1)9?a>Rgp!?WIJ{lX=jiMTy`fzNyo8^gF2b<^4`w%$Jc)0nb zvuLnwprosAv4tP>4`{xKA=~yr|LHeKK&5?Ez+W&WKh?puVL<>Npc_+112SyTvKf2e zf$xs{zV$8ZCEh$@e#I46j8A{+_G%wuu6W8%TZYeyYofDlqg6=V?T>Vc(`9ojOMi0g z3Xfi}UYy%~m{gw<=(@R15s^FMSF#*aR$2WEjLU$@iERK``j+(C7HXx3O$deJq<$8i zd=OO#G})$N0WT3DhWPUAGtZ3g-1qJA@~f|m9olpWCEo5E*${Wk`8{QIPREqH#5{(3 z)iqc7jnC`rd;A;B$4?&f_fq*j7I8ks_>~`VRUh8W#2@-l#^MbAUa!Uq7de_QuIR&? zE+Qa2!R~gWOz>281Z0Ex#!mrA$7_e*7|%TOoW|}G;|*<;PM$dFH(al;@o20zqZ%vt z%1fwHb>bY&i6bR3V99fY`WGntqo@db+}S61)HXJd$dtgob$*seT|C?JOm9$AM=UlL2QANPc}dv8TsKp8WeeNuOQjMVwR6w z)L{MvmHre`Y@j-QBy|Qd-f&-2jhY$1Q!*V^i(q%?`G4z50^f_GD|;K%BHM#A}BZjox54y}(7$;j_+C zP--m;IL-@L;yWH3-4_7#*)A7Bj4;~J{kGLoZX1fQKDdyQa~Y8KuR?)!(6|DRIa`U& z_K!k~Ep03Td}y@YjGO$a{F&r|NeAttbfGBe0vucGf|mBofv>K;=>ha4zw`%K@nvB% zx@|-${wPmhK|7+d>v%a|?bq@o#p5z_N5vRu-LL>niQbg$U+JxGxdK7q1ALLqcwhX1e=Qwsj_FB)C`nb4+s8g%-g>+*tIexEeaHC;yx36ftXb0GPk6kk$Qyi zFCKnotv6=`5gCeLCJ7;FE&2v|xZrbhP&U6l+;1XjU=CgMrH*U%4P-0M_-I9xBb$q8 z+za16|lG5`tQUZc-|e{UC5qn7P{ zC(|7}131~{t1FxbxmIpI#qCY@2+C9D_wMbZe9eWk=;QC5JHcDQzZ2|eyXnsypPsnV zKny^z1l?r8QXXW2KLh!t9r8<{!_bLJw>xHcqREJ%zl^^M2m!0S+d|a?@Tco^COLe7 z)^r8|{N(34Y@IMy2LKeuP&qz5*2SN=N>&3kd2~X|0=wnTR9`QA>{Hspyk#S_F?MTE zyztUXI$rjo4}gpBo?UX;Wn(wr!$o*?#PIKqb?WS2|;K>)W2&&eK9$4E5(QG;GjHsFDl?E|JPws|!7zWcs49(d?M zUzqSCy%ht}|K)%1Gkz?c%?EMn-xB16l|E48%`Qf-zu#gNYA5Nldu{~yVMAb+C$-z0 z5Xh+1{Z_Tmr()!i0EUtwwI5}7xtMiqLF;03f1+^H;>_=c-CMr%u0Kai z|J}y^RNi$Juvnp8dEA)a+|DKuK3YPtP#k%Tn7heiUE;=Q4ro*NWKiwlrKZycl(_bK-DK`3ZKVi~xmGGTZxU!pa=_gyV z24xBRqG@#KQ~DgD1<+c{{s2nk}6$Jtw%VNxm@HWA7Fje zcicDVE3kxzJf^yBE80_=MK?@FrznBgvgnEq3e1xoDQiP^+z*#^s) zo)IEkg+ScduJ53$d6jq3%$sy%tmR0Q=5k=xLT)K5ob>Vao!dY4sqyna|5vpxI^{XO z*8;F7n~P@+QGUdoG0R`B^~T(sR4{ z{Odu{_9Ty5<=(_5uJGpo%yKzMU~XCH3);kg2Cys{{KiUyaz0;$-tA#OK}Q$y{^cJKqW340R_sL2_i@2BgDE1~E7OLf*lzqBBd~$SAc;o!BXw zOe3mQi{BHzPtq;d`8t@y+$k+RrS^>lGm9SAt9S)2S;q`h3B35>DMo!D*PWV#L2fny zzW3t9#O5j}IsT=K?i?GT0%Vb;8iWO~Sr2lT{0aCjhwV#~(bNz7eE$>%4t-#&>P`JY z@y1*3Bmt1Xvnag!>Z|l@m%?TxR} z=|!&SY#jP7(nmh>k#YWc7mN+w1T9_IK^HH7Aa>l*@+L&};jRgJ-k6Aw{zIqj#)o*v zL4H|&yC7caj3el52%e2(`c1bWONH<|9>(C4z#jrcSpaVKhZr)6%6DRM#~pW$C!c)M zkLMzc3&iW>#;I||6_<}se)5wN$#+)i6a0>-@2X+j{z|1{w%mZ)H%*q@?PQ_deJ9-A zqBD4L4x9eWvqGLFw*^S_k+T}+`X(i(AMII^?Q!Y4Md-b*BUDv(K zZ{lR5$3`T5TUHfcE+M#I%18Qeyyg?9sh3j85MhQ~>OenWjuK4r5DG2-~Q%!kVxP*&JSQ{(0l#OD-OlU3~dC=bUrK`kq|m^5$6a@r5+SjrgI+ zeG~l@H6P`z&+JTY>{a}|9Ck~hKjHL475AAE2@^_3p|Q6_$lIeuYMzc6F{a3x_-#IUkE`SOyXGp6YYYr7>ovZI$w2f-P?gFQsa1^Y$)mORTmx>)C&@+SDt{h2>Ae)cc?xpCz9agWoydj-gPf%cwW zjAcFTOXufyUCpahA}wL4vYW#y(uN+N5IIatd<~ulrjqjFqv(*#Vw@qAsR$V zlyj4*svq?gRz8**Go$657h`ROd?%RLO`&kFa{qk!1*YuQuv~U6HD}1&J$2*-03)>#j78m(*l;^i@!7p8p!kZ z*w(yaPxbAWL$pv6|$kpD3m15QJd0>4f)`^QSi7g6r%xux=b4Xl3$ip zQqi%QQv6=>1K5b2z7Uf#0Dt7ri*G@TuVxdsH4}KpQ}s(ft@f>cfg%>F#P7>r{_=R_ z(MQKVZPL7;#~1zcqMN;E9~eLVQ$IEKtnbl@kdq$^;B4G_@oyY<<%8eciJ$fjU$B!+ zaAF^bx1{Aad3>b*=nt%so4|Mgn(Gy&R6o6$yf3!MFH_w_U1t?5=JYN9Q~`N>lwAL~ zKXJ*=80fGV$1qP&!p-gUk5D5nD2pc*ytpE^OMz z(yBN0=Qn%l&%Seq0*5{PJYx0cDe=n=W0n_wz4+owdhBZlTAWZ1A!= z`@n}iA(0&!bl9=qb%&CU63qaT{yLojUZ2JoO|Hlxb(8i#?@C}>ARAd z6GC@={h#sRyW;}ceKg`v(9H4R*CQf*AwM2iU@D_+3-S zRD2@&mkpG6n-QnQxd^-7xYAGLvwaW_pU86X=yB}8AHC*xU&Zc1uj7my3K-YI^Jl%m zF@Ce@)}epu$(ymkJ@Uw-<6r*%?~niQKlvxV(|_?Lmy9*u_{?I@y2|%*&OXa-e4t!0 zpkl%~1_1S^3|bI+0rhdRh#UNF!{k-jOrMB zi1_7Mgoc{lk3o7+@>oNtmYRa2S)-pu9AF#|3j(KN@|y0?O9 zf)!o^J}<*Xl~Xx2T~fwc3pzkNLo$^=#RSgAf9O<_*o!mhCJ3QaWpTlLPv+e$hKuM2K) z`Ou9bq-`)C+8JvzrRA7QR9*2f59hpXaT&CI4*enJ_OVWXMoZKfpZ~&P3mry=Bk~lb zO}LcMoZ32pU;qIB^hrcPREya5)p*H>*A~hT<@k_X>W5y&3@SqhG=7xN(>j1PIG42Z ztI*h-6D30*BPjS?b#RP0(2bu;H^dJu!t~23u{JReF)bd)L!01t?gVcEza4tzq~ySF ziW4ns)J%6*A?RFHF~0ehQ!|O^ZWI*I$N^*ln<8udeB{W&NPrD9)SU!(!pNsnTW|v7 zJFmk$*xFpDP0*dIVM|#DessOjx8zyjSL%VF!*@Cqli50c!!lzi+gTvQ@?EL&6WtTA z65?1oc_S!~)4-HPbFu1RvHJRJZ;Yp&e%gyHd8EOVxLtSMb=m~vWmuFELWY6u#k&_} z*pD4_?%K7(FL1c)t9SX4&3r%YO@AklOKD!PN&l%68{<7c@}BW7*q?uyAp4*;N5u^FJe03$17=@ zlP9yu@!c=Qz>n!`(rNeCgyV6`JMX%4Jo@;fevuHH)!sw^e82P758pN}z4#LIVh7){ zNR^^Er(Ej5ScO8|IHBmfhOoY ziV5C7S9J7<^M2BRmynpelJbeO8Go=I=i2r6Fq#k|md)5i9(WQ`{) z9DiMM76Wbr`VV;3hg3MvPf==JmW3Bv$U!RQT=>BzakomESQ*z%b*4sKF!3FI;rNOH zb@HRqYNy1JjdElFw}}cHTD-2U^CG|4Bv#yk;PM!X+QH13nc5W>?vM^|1h0h4MIP5|cvL2^?t> zBV5l3As@<@h?7?j0T+Z}>LUxB!R-W6^=_s!f@eVk5}Ucbc~klW)%;sS`c;maGi2G- zu#c(F3RH}yHmq_HbwpR|g%mOy-`GIp`0-=o$l*idAO8J+FmC#hAMwv4d95M(PSy}G z$pueev>|hpXjv1-NA!};P!0ZrpoBe#*iGqm22vE-&rFi0@JtoVI~bSx_nJq(nA;cC zRX6AP0HSY-1x3kt;!Pok8k=)mUv&0bj6W6o9Kw7WBC^Rt#~3rG*AMcG^Kj$QJ;g>i zpEX#=hC#YzQ?|?^J9)yS#;gRb0iP<*N5=#f*P`fQ;2Z}J>cHU}Wr#?iKQ^|2c&GYH z$a6k_oa6N8jj>}L95ygve#a=9Pl@LC!%zE4eOMQX4_;;Xd*?gBTOmJ@)GY{9AQL*E zqHZz~RYp-Kp#8$80C-{3W`fAW4$X<62bxEFS30S5XQV-tk-67(g%=lRY1$hd0!nv zmkxJc(YQn6jZsV%uR6c)Y9*Y;mrgcp`1Oc3U%Z{UeE`lo@8G!TqKn*CZpV^=|0Ej- z*<9PbCf~_}*MYnQzWVih#w#zsqB75EvgpPSf9lBZ++BLf#pAXQe^d)Z87MqQCZRr> z1}tmP`6X=6n+1|6TlCI=|9$d6ZmEU5`wjhyvL{N#p27ws&`w>;i zXx|_{VjNjEf+vn09bf*^m&Y^DJUe!2p$wjb4LpBmA2={>z3sMf;e{9a?b?0fF~}Bg z*QJ;#6&xS&(OKdk2kpB*m9NE%gufF_} zH`Dfw4VwL6>mdEaU%=gE?(F(boHl^hTzk#9_TATwz3Y4Ps2QQneB<74jHjP@ z$}i^PJK}y3nrQf#jXie`PWd9&PQG{V1yb3P-n0k$c8tAy_o$vH#;N0cwLx*AkMVfC zbn^I}W4&wL8{SJVy~HnN*|&ecdCAa|KhMW5-T-9`r>pQJKr#@9N?Q7afjk-0odpvj$s}92X$g)n4EK{`bc} z{oUUgfBd=6`{@~eBbo2~6Gt1zXPmFNS%+hT8~9;_%MFgb{x^FMI3~iA_D|S&!$=uB z%ICbIa*1PN8vnviV?z{jwo|fz^gy$y?b&AO}okxiUTTHzzs&Wq1#Ntw`)Wr7n8%EV_D72v77@nZG( zhChld8!q~D=C$DcZvexXvj{1fi8%ZD?+s9I;~x0}3hmVb$`7-rf?EL|(fr~*dW@oS&)bywC&$BrH6bfNRanpCAPGS~A99FDW(dY+6q zd}JQ%Jkb6FiEP>^yr}`2MAe7qf&jumJ-?zrf{May8kM(NoHj)a=2Tm!ZR3}~bq6m2 z9GW0&2Qp>fYhQvFMLvMw%UOB8yFq_#ax;mx?1Jp3?sNhTtuJVly zo=#AD1T2Q!i3=<#x*LcN!=0SuHg5BCg965YsJo@-!sgsm2Df33sYp%IkcDUnPi$y8M zL=PM$3fjrNLIkiZ2ETRRedEz59`gc^m&)LRCl3AjH*%Fn-EAMfZR|gAP!m5|6Nl)g z96PIVB}KlB`6IG(-UPuC2P|nzymHd#h?|Tbn-)vLr>~?C^Wk$W%V+B;9@5-htF~#` zn!xB+JYxCsOD~VF-E;SN@uim(uRY~eKGA*A`4^6le*9zJi17VsD71p(F8l7ExIkRp z|1s2u%Je1spdvVR0QWJwZKn*>Cu1)99p|tImUS>6bqTJuxSjRq4TMi1!9}*(mI=Ey z8lbte##L?es=rzmFfTfURUE+caw)$+NF+A?JJfd{e)!?>t#5wIci#8#d&?3*ue+Ia zaJSd$bRfeEMEIWYK`k!cd-KiXqKhx~#?S3&uC(3MW-2g#`I>>-+Xf)OpSt$lW;T)B zJ>|RV0NnVbdqID)YpI613RXhT3=6&fWI&@R7sgJKw#3JpSlo*1H>C z?8Z4Sh`39;TNTAW-dN3D0>6b>Qf%7n>2xP9HP(1p6_ z@_fozK~8?@({j@W3Z23dYqtv}*|oujMoU-5w`Jl1-RxxjDL<6K zb8K*7gP)6onsM;vIDVY3nXm~)2R7uV5-y(fdI-oIQg3|LhWLdSUmm~xTfa4a>$iVP z?R{umaPEa#>`Dl|njk&LmtBuZ;Zv31fR*ZDn{$EshA%1!rVzncdEbTT0{I0Ey_qk_ z@ZSVM^9uZ_qV*S^e2JBm>Y+cOR)A`8*arSu4qk};0mGc<&+|tcL5|cQT2++9Y$Dm! zQZvr^1Y5Rxcyh##dX0xX~X8Spy#$cVJC#< z@zWdRHFxL_6fYC~#3w#J{`N2Y!Z@mP7GF8xf;w}9g>g+|p7R11+}bqQt~v>k9I=n``F)!gRs z(@kB5L~QhLUwM{?a~KF%;*9deU<-vSnCzO)x(Gj&ml|lcA$;nuLaEOAS!X6*j#@gs zrs7;SF^49e&la+oyUMdsI&|a>(RX-rYoD#0J4rjoV~;*6 z`cW?|kYXXv9bk@Z4g&Vujv%Xl>1A{6ld*K|(c=55C!ZYOxbIu_9bo=45inWj&Aa){ z)sKGk!(*2ggMKu&VuxScjpMtWa~o}rRpT4*uW6+4lSQv^RZsd%+CpWsZ`RW~wgO_y zg=4Fw?0!J1Qopb*cf+Z3z&sMNO!>vzd!KmXvGIk^e`)OAvs;U3ZQ#(43GwlW<&{@m zH9q=b#c9_r-~BU)#x*~0f)uxtia!?{97Ex=Pz$RkW(rQ|8&RHagx?jb7QjK*O}5mw zpsCv`EycO-2g+^tp~NHzhui>F+PD&_JSD_=B-9sY^oLze^lTEs4Vcq;dN`kJYir}s zp~K^=cYkd>|NQgb401ui3zP~|&-Xr75C!QR~jvx1T>$w1hYIG6<{B+FF$(;jL`uK@s-mvc9f57phCvt6xm(SSn zPJFc+egtX*?4XSKG;nhXpqh(JS8Op{*Qea0@^`EZ9KO zM)4)KXh(F_L~EK`N_?=w9ejb=umwc~wJUdYxsc~a@bN*EBbqz;st0`wj~xryJbwJB z+kzO=zqr7$cQ1YS(D)a>|F6bB{>Q&OUV8DxarW8!$JqzY&Z0?jEl(d~F2MsJZ|BA- zja(hcn-pKEpJND>h8UCt+bU`l_Ea_Ka^>{(OWqYVFo?=1l`-Nrs)fs0@C*N{b!j`TY} z`VR9p5Oa%oZ3E^JdFopQEnAN3e_8*+3nE2XhyTs7y-k91CSS@|>+-8$6+kiV&^s$a|oP=XcqXPV6k3Bm6Pe1pU$DjRA{^N1@_z7PG z=c_t?v1QM39`E@|OY||>cjq)4dWz4oLKjI6WpFcC!x+|gEGxShC03To#3sYP4HolIf6`dd?(5sYSEAc zQ7K)?8x9)Tf6AIc-GU%1wTuTY1&g^6+&Nfrs?aiE#h!uZmJ*o8B1pWGuHe$}8c;ln zD|()n7Y(wqu%geMsqocLjl(Wz=k;e&^BTe&lyK!nWJ2(jGRfveRU+aSa^hvM^+a{r zi!=G_`g%oZFfaP6Y&+<+F1%7%3rxRcsp8CP+un*do@W4fv#JS{J3hPD^D{?GT068T zd-c^<#xqYp6*=w-DOq3JJFdC<3Tr6iNnI9J_VATOm*0}B1#>ngZ;Y>g^)9cuiG98w zC*Er36DLlN*Is#TeE1``jT>*g(Z6};SNl^30e;~p3rrsG@l{gC%~g*-wyoNNsJdZ; zB8}kslCAhoK+y!`l$Cz#2vRt{(Gow1b!e4`MRm!=i}3RpnC}3J=)02(@aEDni+-+f zI_7Q{zR!oA)8liW`@`{y;<2`8T{==H>c)wVmo$Cilb`TiK~8=whG`pKjDa7136kQ& zMutaR9R_w3T_@`Ae$RLis_K`fq_<>BPi=&;Z@~tE5S*!sIq{FO{TIbCrvAj7eEKE> z%vW{0Z3vIh?g#3lyx?g=b=tFMpJE7~MAQ%H8^rY7bI)_#h=m`~vABFwpWC&zYdrPD z6XTwHzCI2eIi^kDe%a#jTOL0}zwAjT8&CRp?*3}isW=@tcwpS}fe(xeF1W}STlgs| zw=;fG2j%%|ux0dU(&`OYPK;2(=U9mDw$mSd|151dVLJ;yXf)|37T&mOT<}}24?g(7 zc;JEiy~zde@ro<28jn8mm|rBvhKl||e3)l}EOdBFc=`j2NWPo9a~IJe_PjBDO&sYf z9Ro{A1^P~HobtHCm&-4|)W3gx#T8dM)_EM92-IQ(m6k@93Xu~v!#Z)(cAG2B=mW4} zUV%@(nxnj7vUs))4xjiOYyDdmq~}58Q=c8Y{dOoM-1T8zDJ4lg$V8_v z+}R+k=**m&IJdSl17dLDUfi7h0U8gk$2y4ku?pz20Dvxh(O=>%An_Ouxabs2>0H{@ z;i17HMy_|k3cekK?qcDiowz9HJ{SANW;yp4>eF#kp0f+mRtpZt4DC<##`3Yu2gra| zwoIi(golT{fei2s1Uz? zaa`-8%)fbx=&2{47{B~Wzcg<9@U7zrzYi?jhURF_6~u=pns_$^dVKD4_?W9W*JD>U zjKg2%16-lUr0nMydw% zAf;>_6u`3>P`34&KhpU?92y6RmOm40qL=;H6?kB%E``emDWoME&>atLjSf#SLRe5; z6ig~CD;*FJ;e))#xhUk9ip@bv7X1)aUhw#Y4MGDpFCc@COt%jUH3lscA^eE(JEAAX zV~=amt+Z`m;>s(p9OoQ3+lylOeP|FR=HhX#n))Xbps@V1QT~}E=lBIp zyeNdfuO#LqiEc=#bJ_~1&kWq~1u^L%QqH>wUjHOIh#i}TymV(?(ZR(CHX__LwLfg+RX~`B%o5zI=!J^6qiL1?M49-|4m!QcoYk1{b?hPw>Rq-yvjN6u92;$|e4t1BDW` zzrz9_IOyG877LD#bZ_?GW)V+uf=PY*<80zi z%)xDzWgG`7+(KprK&PX^6dX`RxThF|8LAuzqkR7_Fr2 zpx8KsD-{kumi@a1lR$lr@uao{;;%KI8PHcAbZipa(KNRMyrEA0Acgb=rB3u=Hl;~u z5yi@dw6#}#p2D*J^L*AqmS_M+OoYAU;O2KCOY$e`pY0>>(!eV3xL)uOVtL#^XnVd1qgZdJDcDwpiS@_ ziV_2@5YBYqmhl2Z=P6#ZrGvQ>>o1d2c+;85r#t4<9If5h6y2f2up$#ECLQTm=q0hB zGJzgEk)QDs6o2zYXZXynBACX*2Rc`>D5C-<LM?`mx=bn3Ryzt_SnLwow-+46eiYuLiQc9L=;Dnoevs1NZ>Z1NgKy9OLAp60Ky8 zngqGPfWO?qqu#ztr*bYlh_m~oKDjG&&)s*A2fz2AUx4FD)cqyDiM+OR_xQ0-esWxJ z(FKaxhVk6}U<0y48$oXnD*)-s&dMj*aLfQ~(PAnaB_=ag*?oho{D#zWoj9&!g5ac( zmpy>$x+o5!6Bo0awfG&|^cYG$q40;%;$>0>0g4Ss_~1!jOrI7_ws)%DJY{g_op+8G zpMOF9=v>7`o3|5r85I4+7a1hS#$%nwflrNk9z^_!}onD zU4Pwm<9+XY?>PJ50mX}--QuNW@|e2nFPnPGsFQ>%CyF=JT!i8Ga(8(F$0K>Miv#cw zJC%teI!hmA{@k9jNjMWnn}*^K>eZWI^x_|^l-@jxixvRm${C52u*&$m^G$7HwP^AD z3)%_3VOB9TvOaunLS9T(s1%&Zss|*YJqI}t9fcre*$akx@s;Q{CSKluKn(m{ZEb${ zsEr?Z=zHT=Kl5wjU;V2;@Yvsf_5tCo_0_{$%=^duhhdxLCIpru8IfxW-t!E1(A7#q9yDEER2ac9_df{+YXGy zXF>PJ2K#HjRj_ZyuJCm`I0ZkIQ$)~cHL&Xm*=(h!QqYmKMAQh6il`Ky(y1ManWDM$ z?~4&ZTW7X2;b|}iL<~%{Qa9;G7dUgJ0y={6dL@IYjv35fY1gf?hAM6g<&xno*xmw= zYDp<0TXrd+pSjOa4o&T_8LG}cA8M|kA7$-z*4V=f3pF46#aCi|{)OkpPyG0gkH7x& ze@*AHQ`07R_pWvK#Q^gpF=G?V1w!ev?VPI{(x0l&m~OTy?K-8+S$lyfq~?>pNM?YA z58-`xQwpq8Cb?M1T*d5NPb!efJth=9DGv8`~~nik5^WDIVb1)!DbPE&N*F2Tz0CDcis-Y z6}G$`+5z?nR{>;@xD!B!N~E5KDR9_R@2-yIB|;>%=#za_Jsyl~TMnXAek1JnrITrkbjdg9Ka7h+6~93({!Ue^T`N%8zvAWjLqCBac1m z$8MxRbZsHEaKHSr%f`9q9<)DJtt0va)W-u&dRPqe+m=r}{q*?ex4!8+lvLHWmElSy z3%}F8L%MT(?BkytyuCM9r4nyXY6(bHLn#}*SPo#ceOTm4sH-rAa*mA3)Y;ih0G)$4 zuY&bCUeqA;R^hhklIu?_)4ptWIT>+PHsqEf4G&|5Mf1J)etkUr;KR9_tG4pv)QSan zdHJcHPkj7G75{Uz`I%2-#L4~CbxPZ^Xz)f-;68}&%IDNm0Ky%}?iwc73^mF76Sfc? zyGcO*GLsWyV#ArllElC=G2*`KyLC#R-L|V4{&tcPjQg6+Cf?TMHd$c*!;2? zyYBky$BoxtHx3>=*Lt{c;C@a!^Jj%Bx;=;|D;nhp0{YGCf9LtmF!@}NNu5n6p31sy zQRRL?oGhuLky5D*tH-VQBVc~?_+k!h*ftM&J{SYam{xi%6S^N+MVG+tLer5pS@>YQ z1yVmmAPGkd;}v}rVd15hJN+@2{K?}yN`J~*HU4 z_Os*lH{KX$@89pI6n1L^ym!wYUr^ZC*znu7cd3u_onmy_m5Pmx%12*Nq|KnoPd4G^ z(_y>*bQR{Y;QGODQq@%jQrJzP&e5|ipsV`VBwP5-XAUPPUDg>$Ul6TO;R!e^Jh*By z!;MjfI@IM8Xc-EieK4D%*hW1+v>CeLwzo?8tKm zlKcet$o#kfx4APCM8AN~Wjjx?aNiQ3#}}a@tCG>coZAXy^q>F5@#p`u|7;vNd~}@9e8HMv z=g!@dNqsr2UX9{;vz3d!8k@v6hh~eQEu0OrnXNY$1C<)p?GbPr3g2bM(OhR?-EWBx zdRf;_oWh~2Y%AyXpDI97eZqhb0?Vg2m{k02GwjNf8kISHITlQGu(!e6k2z0E^tlY( z@gkqbOASw*Lqp7>Qw$Pkx`o%bK5rN;eXQMx3xXim(W7oBs+JDcFGaMsIj9C56&7^cGzF*O=ULx;U$ z=LQ8AycR*+Cz^HG4m#4wI(19C1H_LdG+*ai-h8A*_omZaO8|q+0!n5D zw!;Y+OhK1sCD!Q9P7DG|A1k1#s%>*<0QJE0=PHz_#K<&9%L>Ed#~FBJi;aaa*v#fr z1DU(P&ptO^dg&$KIWxQP2lnq9mt1m*A2mfD?dU)z11#V*f{5G&K63QvxZ|#`j*}b5 zvth7HX-_JKzx0D!ZoXw)e(B}ogf_&!i%}D1S_1wtj-NOo+^Mm5?>_q*W$2W_$$tEu zp_~zeS@6}197@6eFp%~^MtbpqvWmUHOM51s-L6~|pqxHeP_oIs>AQaqK5+l|`Zw<# zdv@@!*BX=bm0SSq7E^hd;W#-t#95p zUU~5a|2{069QqY)?kGvlCnId|TS;H(aJwnxgS*HZCyy)37|o;iUZ67Q zEhwK9JL;M`u|-E%va)?jvOBb?W8>zz2U%}=tpVwSDS!NoP|3@49L?KO4fGo z9_#8SywL2Q|K7hCzx~_)^LXLK=f?#Xp654h^9UsUiaymny$lit$Px{Swnk8Ao>&!IESYeS+9-wbUAs)wC0eNMKGO}ds~ z*&o33_8{|9yl9VpSct6G7|!xRJ297WL6nz69`mn8{K7B%H{;WvzI_}yqVX^1p>f`D zHB>f^3un9Xf>U|`k&ADA;PWz;U55oMT`91%%GLc1ou#+Yzj9vC?5PuZ)}tzy`m|r_ zg`{dGzVv&YDW@HYnwOZ0&wf=DoJWet0?dh|L@NB& z4L7_!*TaGWsrFM{*kaP4Zs5h>F-DOIgFL$EnBd?+YvE}#VwUj=9=-5ThDYaj@g!EF zbDlI5y?`8U72<=k)A?VIC>5wb&$x<4c#57VbbLeM+Xf(13(maDrdkNw*}x`=tX9d z_h(6>YGDI7lU5HFGR3>p3Cx|kpnb4He;DP(KKVrq==?117)uBc)7t9f58ECb$byD3 zy1krM&y8AaMs5c3OfXv5ayOPmtrlY^kDti*61DjDV~CnudBM=N*Ic7T_$mJuEpN`9 zHnkodKy*`o9(`lb-~F|(`S*ain?Y4Qm=srJ;p2|nwbxub-uK@3d9e>r17cyf`I8{J z{4-Aayvr}A{8L-z|G*sa7G6i7YdpeTgH|-qTM#HNNtduZ#_T5=iZUJ(}xHZGgEb@sW>ybXo$>&KKav6+7{sPRBGs>Zyb7k-23%!jwhdaV(irhnBT7D5oaD9rmy&sVr>w5 z9$|xVLL0ElF1vJm@I$wb{Ra+cLo8nVMZI>86B{RdhnBJG$qW*;vK!)*PuzEf;JD(n zlAUX{5iC@63Y6eBRm$7F-y9D-_}%gFLywGO$BuXdy?^gsk1-_B$yg+kJPrqcHZ?j} z?2_X{x&B>aD<_d(4yQ|J`6&!+vIt^>3pbC`al(D~yRRQN-E`B~w{NfG%*6y{WP=xG z;e!?}Lir9O_N1%(4gTJzz8!fXM1^M~kp5Wqh2Dzcctuz8X5g&KH;6UiHK9K(0-8Pkuf zKdS+&gznhWhVbLE=1VWygyRK%`_wtM#D#G&?} zvn*iJwXi`Jycg%TG5aw2-@Y!Obxj~LIvQ_o^sa`6{w5HPa}=fNg0ntivg{XZ zF0cBfJftc+nNX9$q=52{Y4HbNZRv5a3ZZtcbi7T-3{~3oZw<2N4S5G>;iK)8KMgJw zJv1fm3uIgrP%4`0pc*>AMNhIT&^2D|G5@{+Zzksp+Plqos$TW0N-%6aCc&!HdVQrD zcxqObGT#$EeDv^G*LmuH`X7I396axQpSKc2_|p$OUn`!+jvi-P&ztG3x@Jg47xRmojC8_i&XL*<4?6!G+@kANru(!pp=*`cywJ!h($*k$OQr0|tdCWZH`uM9zRsmnxkUtSAz+ z49BMUdP3liTgnYqMP2M)@bLj%F6m!%W)?t+MQrQz;3Y>dzwqMt@|W)z$4?wpRp94@ zFRJ3St{8vn_S?rrivRKB#}pSy5(CFZAb#o<-&3|P6wLx%;C6PV4(#Z_&oBg6e$&TR z>zn$yUOIRq?raxB9WU8~C0Rk}nDPb>-%LBpkK^vy!^^AE&ggfyHiJN-u^gc8d|&dZ zr=L>1zT^u6Ybq047M_HJam5MM7gtSm z{#6NYKm=)fGWrn8Sa>Kxqwdf}@rIWEM~sB=i=yNUk2^p7{fEbQzI&g)x5dlN929uO z$Qa841n;DS`J(ziFTk>T3<~FxWc!Vh-4}8aPpeRG9>2#IE;MnzzUs=W#x3uE|2XH| zgTBC(7{qmS5<@iji4YRoC5Ck5k?!W3E)`la#MV~>yX&OdkTS>H4G9y_-DUVyme z4~N0oWP(@8>}gvF(0%9I^MPtxci*|lVGbcvXAbnlZ-7thK^`7>n_w=LjGzcTB#(c! zjTf+mTZAo$f<@L~b&~f2+6Bs$Dr4W=uM}t6118#U!QAJ4FzIW~E%a12qOP8~;avi9 z+u;QEL;o(p5_Gc4Ta>)@^54t>&l|>xgM1oJhx{)a4UXpmhu(Zfw-d>mCzUA>kyt9{ zF=0@t#2T9mQIx}9MB!RjaLgNgZuZZB%mPi(7Y8VScV@xDoCKY^6$5@)_r#>^Qil`d zRHp?`b$b1SM1Z^rd^ioo$b!%&JyMa)Ny{_{7vcW+cLd!YKpWtoUj*7ULr4ZEls&KS z(EP2IQQfIN?lUiPyrgrE{Vtcic0OL);H<@7}IR@)?F}V z+GnrdIqxw?R2@u=7U4Mek?Vs54dVBCZQ18z%O+h;!EvMmNq_uscZxQ~rRI9rneDv> zc8s9HOKOEqJr~$l#xv_GVj-GMBVU{@r+w01g+sqfKy(Jkv(~AS(D9p8A7+y*=TvBo z=Yu-x&s~RN2_TOiRtNk6?k+OI#a+1G*#vI|es>|s*z+!@Mzy)q$=$mL$ z2T+4h&VO`w_`#Xh148*WZM{j&V<4p?hQ|=*P5GIx?KZUD=4ss%US(sfi%ABaOhU+n zy(b@z)&UN `@oG;8oU5uLjh%7!YK3Je?)d|)xjW}tMzMhA90>E2?~N3LY^FiNhq z!ujZAIz!2Xx5^8E#i(%DpFn!-Cv6*DhQb9} z*RmZ#oBASo`{|5u@Dg##g$Kk7w`1;0ZZM-qev3w&jvYBXzVxLp`E8GWkq+`YFmpWBZ+KCxy0RHE*0s(qy-Wf^j+gAcedZhjF^ zf!(~Vm5U3K7Yk!@eb>4#Hf+$Qiuvx{JN;w=G3IBw{(ryyKaa0{{p+9>| z#EE0lrS?`^_ofgJs3*C(Pr1gn>4W;x{uG;~c}*{Vfj2;ciESYR#WuPx=>z%-Ec9Bg z>9im1xPaEXqGRb-0aKv+EC9V|d}dKj#;DagHsCLEExXjAeA?c{$z4>qFD~UKAlAtx z_JO7B1SN}}xt&&dTgTjf7BSv0qbs^UE8ltn>O1>EeFF6EhOlRBrpDo#c#&V|oIpi- z2dV9pz+^@ImS{xuW{&OC7;1`0%#@9b#ChMlfJO6(;u9 zvE-ihZVOY#>H|a&gmiOT#eUB?eU&Da2bE>B~Hx`KeDvfCG$ktT~2xu|2a1rlE=XFcGJq2l2S zaT4~sVQ^6&Dp@Dt$~p-};>C`#9LZB}DMhdI)G4-&B4b{3NQ2LP;P`+yT-eKb5-x%9 z@G2FF_Vava!;rBJ!Nrws1>UPObm-rFhLo|*yh*lP6)bq@za)SZmy5mAc&AYEs$<2Pw!wdZdZXc;P4HIGCit-9l(;J6fm4B{kqEVLrmKUobfUvrXcB}! zv2~{*Lt{+3z=clU?NWW((yazA%fTQh!U}Ey$V}*2$!cEE^4)n_7bSAr>7Q_=E3)RE z<-rx*Q1xA~Y1_SNXe>9u#S~@`o%oa3Hq0OLEtpcaB%JvEwmlNS>yc^d)k7L%wLi z_}=%vcU*qORkBS?TV48!>mz@_^@J3F9>5kcFpn#Z&`jS7=!MUQl*gzuI?ApQ9I+W2 zDq9Y|(6h;MP9OAbvrqiX4Wh67QPd%Cb!Y>uO&s4(z5A}OjOSi_e(c(@%XQ$Shdht5 ze&B;27&qK-qaSZ(VkfTlPC<}U3YR(Kj0pPhFM@Q^sc zVrGN;VwellZ9~3l<&!3U>3|g+nQ9Z?^{TR6QrW*vCq>>MYcs(Hr0+mGFJJsbf`Fes z;yb`>hB@5rQRM%m^w(?vPWyKfuhs_eL$}@L?_{!xaV$i4O~p&dDCfI<@s`^7Wk(Q| zxGl-MTB6pb5SwVi_l%45ecpKf%F8d0`yY5KeYX@aK9NUL9+BsJ zy?h11?SL;%^)GwSToCY`9Zt$FnUxQEgmj5*=ML!?4^Is2)&k+O%P$)@-Si{g{9O=d*2b5{sZr@T@u&N9Cts9^4WA=r3Bs}6QT}BsgxAj@HUB#AzKdc23$JiAP zeW#EICA?y3PP>Rb>F_vDIT!F$?)kxjI$GX*G#UuVj0Y_M6&q04#Vdoy32gXBM)k5D z9rD8)dgX};Z@z}e_jcEKBwS;Wxs!J1$%Joz=YjESzxFHRj<4J?_O9<6>wDMy`^#%< zdv)wk`{egN0md4x*jPc2X^%PlF$tgSKzs)03?I!KHDn!6%6zEo`koP@V+EqbSue=j zZo`7U9jwetZvpLBx>s3{T-OIM3q|=rrcHa!7kFV@{N`m`!z&zE`_V#zWvoiVxXitx zHSa=Z2IxwP3{3h{aNc^h$cA^eUvkA)LuduSL3LMGZjz-xlw8h__|Fq!#GSJ0f}>kq z2rTXTL!aRIHv&6FCo2HILMmPttGukkvd`gn^B`>BgzG04;%noDQ2U|Fa-_&|)UXb8 z&H~9!Knz-F6SyLY*;YA$jfu96=(f;v4KZhfN!F7Ic$F&FHmg6MD?k^`=Ky#Fe0mNo z87otkIPipy8hAYU&Y8=vfEpuukJt41)o@KzO^ zb+9NwhyEnt)Usx7DErl6oNt_=^Rq4cXuY6~BsW9hKsT8bSmmri5l!No2P!tEdKG}1 zA+qz)yk$(uR8vnBT5wXNp72-fZQJ75Q>umD@{9dp7p@i)J7xC87hm*C7wn&Gap(8y ztFIpWv=QbvY5NLd!#wD%)f<*49)E0n_x}3_FL|-A&^*Xv`=l0u7hZV&xK*1IE|7~5 z_sJ^fM-6M>Csv4t3O%;E%^0ZEwffRD={2+*u*^50t5V02a`ewMfsK)Ay6hDTC1;gs zH)kI~;#(#c82H<{d*}GhefN#;Km0vyi1Sh$vx%MWir)C1o5n34_<%Pqyb;(2B%8^S z7-ZwIIthm-eF9ZwSAXS>^#|ftP|8bB`VF+!nfOl-WO#Z5!a>62=JE@B{70{{xDigN z$Vt%VG=}|sY3iae4S&nnmJaTwBF^t7KlIRpev7X4!%3oepwDp@C*Ordj-QNp?~lB1 zy!Ymtwb90oVjzC2)(3XFZp0KHBMOtbpoC9?_SYzcBbPc-Uru)6-@UebJoEI^<15+# z9XfPq95`@}AH~j-4hYd#b2`bQCSNzOJn>UliMwgi9Z#@HCJQDM;b*Bczx$h196feq zTz=`L{@JICF1dK{Mr$@;(}gnFB+CK}`5rB{?>3;oC;YM@hSVE^g<~6gK17tO&0{vQ zX2p&QwFzckJq;l>Qqr*vj-*420_$|^$Jgjg-Kmc+Tr@%c`yxRQ`WFwp)PthcP*TC9 z)WN#IatE5aLbMKZx?fnH!z6SD$3+$%cjs-->+5^QQ%^lTe)o5OXZ*8&{(Ix~!*7i9 z4xTgCckhvnQ+dCFWYbnOa^{1KQCYRp&433ias-YQD3=0ctpl1;GgwJ>Cm zsr0Tuk>(7-ja!yWuI)~A!6vgh z%n?3haA$I$^JFT|cv86{r8SW1T}h`F!V2@K(@#MbrpZ(y1poiov;|oF&M`2Yu><0wtk|d(t5=Ik>4o zgPCP*$_i2zSl2?0VI~)pE%CZ@6n53G^0|C!|C`(6J-hy6G;cSYdfAQGg!@QI)N*uQt*c;EZpFB!aSO|2`wk)hlZeAB!^ z_R7>O2J>4J2e2t`{w{9^rD#@|bn;B)&MpC*c*9L0J~y-)5;j3_deRXKo8H%6=Mm^k zV4U=Ltdb4URaaj%-mgszzY9yVL5&t2LZt23RHZEea2+@J?1%mxd-F-Ac+3X~&mTM~ zx1JPjZwc1zOcFEdsEHJOqX6_`(|T1-4C;iggN*@`K5d#h;!6%_yyWWG(WB#wpZ~&m z@S%tN=(PKRd8ISwH!J4?&MtlU=Y;h4$xr;~xcLJg^kc+cR7?v*tVo{uUAV+an3#9j ze@=nK52$2<=HWZ;+?l4XU-``rY!W$d>shVK@=ZY&q6&u%lB?5?!(jdGfIry_~ zVcQls21Da)cfnh6fNsAgi1u(MO}nYSaxzqX+D?ET*gD`O|hSLbrTFiERdObLf%Z$sgJW0G!3IuUO7 z>0KHw(yUGh^RN0aLF+PHyHtTFwMNi2j3MX{({_Hm%Z1e5XEHfpXwUnq9yJT+iDABIJIf z`Ga}n@ZrPbJ@2_`oPXYVelibQ+B;fZR?4}^=UyGbgcd+6I31a|lLsc2(mBZlC{AtS zly}w=~JTz(quCw4GHS`lD(jzs(EUkQ}(!V+;mi9jz-Q z2rhHDs1MsSJ_!F6&S2fm?@#5KlflIw!fgACF&1^rU-T~IqaZC9NtB7^cI$I7*ib3= z`Z#OlNXCC;{cl{GNDt|H#TH=II-)yR&p*xZ4y=G$BY~d4!KX1edZ1PK-Lau3=!Pi` zehJ}qCaG5?4Qf7h{1pjz1b9W8@)Sws&&teBlC&T5oqPf&zsN4FkZ(Q7rPR0?159^o z$=5(wMr>Jw$zPx*sm3ukImwi9`K9BEtFBUdxop;ed1tQ52C@2VGAWTV#q;Kd9ySu3+OB03R(a^z%!{x=Q8FK zKQ#2r@`l!JR`NR9Z%Rd{kNRO>mBH{rtn9oL3=-`;)WCw}rL#+6rI?F%kcz&^_?HlrV8;Z;t|65G_t$CtnGh4JK*kB{B_}}0 zU>_T3?f%B5Oua;#MA``~-xKErbiSZvd-#xpGT(XTt-?3n`0nxJKmKW7K!Nqd$&*Ue zx2kWW8@?WceyrM85jdzQWmi~6ky1wg?!S$9z&Jovyi6-PpsWvrc#uIyu^CHRv2%ZH zS*5KCyJnZWqi|4>UiSYH!*Oq(!+3ewKfl zh_8r%=C1G0{oH>!{_!vWvM*v?e9?tt-~PSwFL72za*C(y@e?Ng?y%659R~sKxi8Uh zf@#k1XMniG{rJsc85c}&02e{%zPX7VYuABt^8ztrFkXkFK&%%u;H*5V6CGvSWgnZE z3yj5=1=zPOAge;hH^rM{p))pD^Yi>cAyoGjW!tw2hzp61w%g2g&8Sf7)c?;}q+e4p4$R1NA`+W8v-k zgpKnqmNrRZC#VRx|H!7l7Gs9$>(q;X-Z;UTBKGXR@wErA(VXME?-K{-;1h1zY@*jE zx^7SMk(r=$kVbXIgLos)dPP3l26X#ex)f9VWnQI?9O)V#jKB0%{ExpqpS=THVFw*P zp{w9lC##4HW*m)?!I;3$kRZ3{oGuZP!L;hhA5O}yw?oEn6k^StF0C{A@yCJtyy?LhNIZGIm#k1Wt4_(94G zW*l!N?(|k+j%o5CpStt%mo-1e$<;^KMF&?N^ILS$Wldsd;@q`sZ9MVB6aH;s0N%6r z@6%?OA8%(PuydR^c6?la-Mhvmmt89Q3G*>2+T;Y)9~QHz>j0Dgp<|x|P}#iku_67c zbS+`x!FOUC8>?yLuuE(rLSHQ&%WVSrFr8rFuQ)nk^46^GyTD*M0Vs}_Tzc6!=iGB0 z=k>Mqao&07jrZSt^H@{NJPDSbJVq%$6hq%ts_z~~TflA9wik7T?63Y z4L?~-`BV;b`#>D*SF#oXc#O=80QsYMd3+!eE9Pro+!K^tU)!ZA`OWc_JMJ8R<*)o- z$KUxoe`h@Z!ZYK%^AEbMd|^jQa$!Y%llDfV?9j*7B)?}b^Qy46wE+A@HcrIZO2IU` z%g!p}!@dTf8JFS&Run#%*KpYa6ED8Ej`m&PF|#N)fO3qXw_fF2 zhxH~KAOOge6VaKxzqefhGJXnHIHE_bXqgrATqu2$ucV!qhGlVTBLO*=MI@al@U9qI z$W3}@m|{>c)ltsi#+(MBgb{-gA4&OuwArY@sF(@wTR_*> zZN|ZzDYra|k%#X26=Lx2M=l7*{~{K)EgcZH;7O-^%_p|rd8n0#X%?Ts9Zs~;x5&Ib zuzclhYda%7uL`Q+93N7ZsaIb_G@dxPM0%EgGVLs0gFzg{kn=w;<~!l9UEK2io2@+- zti>@7hJLYVV-0r7?d#P4%9hLJ6X2UBI@yGcdcd`PJ)yxEc3`qY5Pfh;I$pt z)F#ZE(m-uAUGqs9G1dg+kwGA5Ca3Cb!KK|XX?1*hLr+~Y9#S``GsI`f7n*U@x-*t^ zh?Yy2$ioX=2MKvh(}wtuKK+4m*h?=7HzClS_Z7&esxOeUM8GD>&(uf0h!>XNIp8lD z6`g}7KA->jYck!FkH=>x1{8K!bNujSTXhZ>+SAcVIL4?a&S%@o{62 zLh8&iaCE4~naMzqbEP4jDM1IH##;dh^N?O^H4cDxfEBBv4~?ZaG$45|2|!Jv#6{^kQ`Y;g&{knP8B%%MDY zAz84o**bpWgcfsZGX@NIrda4pH0_fY0r3*7yTAHX>-2(MDQ`kWFS4gkZD?b?dwk*( zpUBVJlq^8JJukQfpj>$Qp24d6niaeWN`)}4`_dB7#IeMa2St!x``{r#uB$Jfkj)xvpfSgq2^;#Z$A+DA4$uD9}RdboJvjl4yh zCT=P4_%@zR#`^f~cfT|4`0|&>IR_5-Jcg8i^k1C>JIW6K^pNn!P8_ojw|?kD1u7iBCGvtMJ9;!em2gbwvcv1BQvf||>XU{+V zj5qE6%|_uk5phL--@ZLV`_=KvE3YXI@PV5fvQ zF`xRCxWtnaa&(JPc^%Rpy}}FUM|80z`5n>~4frH*L45GbVb>QNB;GzsysK@(oP$j} zeuf$UrCV9!d;~IIG%px^;6vM@tyziNMcQ4wIB!m32Od4j*#>ui*ZjEs0}p(6{Kl{T z#`w}#?(kxjN6_Ox`gMqhN4{A!#V>S{i!Rz5EKdXwA_ z8^Ct7Gr|uvD54dnwp&yukV#$E@fP~pM;dl&6J!|(E-Wn7e3beWZWDCdB!$Btxkw>8 z5>6qupDQWZx@(2P=|l3O!;-mJ`aK5FHbdJ^-k;%hzD-rZAexiL*<-9NbTw_xhbw&6 zp<;3~*i0jf4oopG!1QL^c3?i|P__^V(mI$%R)D(eZ>pZaS>c&mrt%aMDapSfyve1_ zGN*9*w6sjX2A`ejSDGb(~q~R z4#!WN^l_5!J*qu#{qSvLHyhx1ZXIxI4N6i#Ch>^t@J&RFrs(X4W2wQ zxY3^;k%P&Sc!7^fK1gcPFf{K%vFNbI55dwVx{5!KH3{X(xi38I9DDZg23akpg+6go zF%-{+-w56PGP>Cqcrz&};)&)}=rZYM+6*hyWj*AqPpbG?m5E&_4P#=wcXTa!n=Ob#~tx|@BR9?>&~x?{cIl5tHV`g9EgV}3U=+LfANx# z<75BX2gXnR^q&~lU4P>^d6JDX{dkw-M2r$cwmq}~9^oH=ZvP8abW|e*SCE+L|x;9zCj!Iy&fgs*C-RIKQ85Ek1EZPuH1)?+a5$ zbOMZ{mtT6(-#7i4pZS?_(|c|*>jvMgmhQy1#C5`EF~#?)iCgy_w=eY~u~qtR<{K~c zL$-`#LD9SdA>tneViFD52A$Ys3^^|Bwtm6&ZeD(#V@FjL;C4v$Iw2Ro1ZY=BF?sjyDElZIDvjPvGKe%1>v z?Gl|)5blPyD;)B$^!au{uk4gM24wj_K4=QgIbTT2n^C&z519!>^Vz)3h&4y*H$(dr zak|6AE8I+NToK-ZGs5(C=nkP*%1dB1*b5j(owRvLlvc~7BNbjy?HSE3D5p&0f##n& zN$Fb23#^+}b>UWQZQ|VyOf?UkibBA4m(aSDF4$I}$o|;wD)QR}4dUweaiHSv2x!DRJYD+z$T~%=f?leQoCW zeM}aF(6peI9Z%L9r~J4kKiP8h#BtY^i9TyhX%_vgU0TFz(`}`3Pk>{>d6(Qkzgm`o z7Le@bepid+4lNT-CJu0uA-4s*%O>cBMt)W$^^GkK>IW@t7aL9Ekyqr&2V776xm|qK zw&bfH`)60A^Te?ee%zVO&z?Q&C=p%Jk_|RRCpS*}kz0U`S0>r5fGdl0p+E)73!m(t z{n`p4S-@rMBLzqM(YNR`;B~k~M50~&i0l;G(q2u*qpIo^Vx+I3<4yM=xbFGd*Ty3c zf6tFiv)Sd5VI}Fu0v^{P)I8S9Z?s-=@nz%Ik9^p7={D5Q{IV!1;%;el>JL%ss5o%} zhwl|r1@6_QE@B|Y%9>y7c<3DNVV4X!#)lbH8B#Mq)mBWgc<$L}z2W6Ie;<7;FNZs& z_TnjtJjyQHGK4MbByjn+I;#{+n=sXZWe$Dh@S#K6H1F^m)%j^LeBa=fI1W+Cs(W^w z@y~aMH7W4MYTr^<9H|-OZ0h^A&&#-?$9+cQEu1P48xM(@wSrz0iF*)%f zR&@yyP1vSx;WcTg*JDFSVq+Y2Nz4qzn-0}JGM6Zi-^CYQ%vL_T7eW$qzgEBb%&-3H_{?X1-4{77y6{53q1^oodGYeZ0e%$j=rULoU8*In8Nx=%f zV;>a@S>d7h?r@cJesH1wp-84_=;FWBII({Vz4WuPNn(onef+?uoD&SfrQgpm#WN}< z0Pp#(bZ>^KuHy4kAk~%)*1JG44N&y<44m)Kl`^hEv@H6iM{4;u=^t8OUXOP-cGK7|%ZQ z-1y)8hyUUDzx|c}a=dZ$s9&6zm?~bfWeMxgy3TsQiHDmTaiRL6eR4)e_s>GP^&&q* z>ICoPnqjq{0bS+IfUop5wEDZ|xX^I{f^fF6%-QBy&^kZ&CyY@BO)PXCaFvAMA3}lW zcCRTZfmgoPF<~Z^4$AV;?F3SG_}WsRPx4Qc5?8g5Lt*^@z9A-Ce(G#-ZkooFeF^Up zICt?FJSi6ZwJc;z)Td39Y$`edq}(8(5E*dTBbGaKppyex_5jdOYoF9_sJq8HeATb0 zWB6DtjB)KdcY?QoVq1ZC$X6T2;Km~G6zDBV2)Y5h5iYqg(hF1O!*qcPzG^?o3Y4dl zY#A&JIVMy(lv`FE!5y{z15d+7*GdO&T?MTlO!EWAEp$xK_^N|p;t7tT?ZAs)icu)U zvU!DrX8}wlt%DRBc}${?iOyn{v8GQZ1_mMn%YI18Hu19#OUa%F!f74-SgtoA42H>n z1{9C>?H+HuacDgC)Ki{hxy!+34SVa_0Gy?Xo7efj`}*tsqM~ERPl~2VqrRVKZPc0H z67JaJs|np-h{XbkDRe$2f0h7$9}UEi$tpHzm1SMROAPR<`Vm;_>C&f! zgNcnP=^bDE;&|Y@_o-ftfgNM-o_+ppUw%^>u(bHt_Z>cTc-(OPyT`{r@o{Z5x!X#= zhKrLolRBp)#Z__h1sPF}E7s(4aYkw3{eiQzyArI^BnIJlgc|70nZKK)*evTyJ^77e zzLR|A6<3XCpL=#3)*|JNBS*%o8Xxk={t!|O^2Z9#8${tShv#_hO&_5t+zE}D*I#>m zTz1)I<4^ss{@3H?_ucFbKX<)3nad0JB|Bg4fCI_J0uIkD@|~wT-q2<`kT}qmd3>1q z(2mG+hZ-DphIbJ!v}1}km(K1(#+iXW?nqORsQ4UJbP5k2bSfQVWkXr|m0}P@iHfso z2hVx%8_<(^$+}x!X^(5S7bymeOWh1))X1k#D#E9#4syt;box8pDl;~j(|9S{yRW-; zTzLMu98oi;o=GmB;o&b+a?&-U2coTa8lU z;EGuv;Lj2wpSDw)Y6d8SCtGrxp|QxV$ZiM4W4;9#=f1GX2KGfGCKD*XEN|8Ypk`7< zfABx;;cUukpBXAI9Ae!L4hW=*0bp9C;O&Y&rj2L;^f_iqJ6}9LCx9kzblK!6d*ChR zkI=&cr9iZ)todMyFNft8Ae()j4lswN&RF#K``lMR&>uW0SPe&Aqf&+f_~@D1D2kFS zY`1@4(7{M9)*P+3AiXv5^W4I`QR=qqhuz-Imq$z!3*vzJsmhG4vWH*(o5lxB&A5Om zs4i5x4ZtED9{=c`L^|_U08hm}ijp;?EvEP@ZIw-E~boATK&lLo7Y#yid}P@ zS<(js={at*;+vnIDIhNc$RbW(58XyhOI^`B1E|!K67dq9w&VaMf^qWEbpSU3HAaxS z!DA&cX}y$#ORR}GC3I$8L)%Py5@>ahu+#;jRv+N4C;cqYHo+xZJs^EVzOi;7c2Puu zJhX5&z~eSyJWN*lD@K(-|`h&~5fFkFs_$7+hQ~k8dJFp7*PB4M20Fi8I zWCJ)3dWTX+mky|w(m~LnPJ@F+T$K5=+DYZyST1pbqQkq%(3MU*>5GPBt*7!pO+I4g z!<>BBo?(`SC3-70wyBM0-~-$#(%@DH3MZWkTeDP7TFBrpn@Ki6>3r5&#?X5jy)LiT zjd&-I90cSj2?t(fUZ&$onV2(xz>9|o)stE2lV<5)p`FPpwh~jTQv2=D#`m6kzBXQb z;d$q&61+QAPwrM8)kc7~Aphi#|D^9U9k07})G-rh`HA1IzVg-|eEd%PhDS{9WAH8k z9ZGP_Kmk}XlJA&v#8%SI+hVC=5lnrAv5z3>i*QstP^U64x#6NgK#cN3HAtyMedkC5 zEUuA(=g{kKjJGeKI>>hl#KZoa>FBR(3@|0zcwP$DIMuk=r0=ray}6VkF0(6#s#XJpufp4$J9Rg zqco6GZ~B{x#6j&#o$%YXXchz|$JYRM@7^_zXw&<}FMM&l^76~RU}3U&(c=qB@`r~V z0_Brb!4X4gWBVk+Q8w<1#|J;~0oD0^mf6@iZhcm68Re!TvKG|=LgQD2+>x*$>vo?u zBQmKeI;f9N=+J00_{s(?OzpkdK^J;4)GVZc=)Ma})}q9p?=n+2VwZ6bzS|7DR?$Ad ztG`)q;?%ssQC#>Suv+U4B4sf09Um$lD08hj>64>Aj9>lJmogW|I191^XYbQycw>C) zTi+O;|NQ62AARnR#`Di>&fB?rtnJ-D*7odi`};zmW#wfVPv4JCaPhb5jt%~4pCuGu z79UoCw=O$xS@O||4nB+~Tm9Zus61K64k){ZP6e}nE{V1|pVaXJ>%I^c+Yr6;u7mz2 zn}xG!%af1HnP76W>^TPDN>@}vQ^vR{F%(4~MW{UT;7xB@o*BtS|@wGg8=m2!;lfDRx=VIsKg$14hWoyVJ zz7|P50MDbLIoannM8KhI(YI@?R;Mt8Pltr4 z7yr}=xvUY*RAU<=PYB;$Swno-z8;3u}gTz4O>vTx@=hq zGhj7YW}+Emk2bfDJ@Lf&rWS_lJZ{M&mfS(%aX{H+gTtoaBOm_oxaO*B{TMVa$ijBN z9o8USUR+}~vrFOA`m1fM!{r5z_7!ipcL2u3aTUL{KQ?aw-at0NX$QziWS>iHN%$ZZ zw0rXKp~)Lv9mL6P4b`&L$t4PsqutQ2c!)1`&Dbzq<=8@I6=*jutjv9ZypAb8(dE8m z9Dv^TVHGm|nlC^pysP-wA&LLF`&E4StM28~9DLviO)8=cg=}&UA3ij`@cA!}S6_X_ z-}B|=Y3^fwG#r1VO8sir&Ru@%G1@+?{`9WvuOBDj6+lnt;h(toNgjJf$2T%kXn)BI z$K$f6PxF@LlVe>Q8R!lHF023YGfeofv4O3$b@bI{x@_S)cWb}=$NUE96WaVcHoM$wY&$>3 zPrpH$x-0KktB7v(QAwaVyf#Y=NK>Eg8?KjSx}=Pf-q_G)u;OE8RN@X@czlsAa}qNf zBED83taxz)z)fP0GS>k_F)9x8LPGz1{leocI>2MYZ3~?bm%)b`tV%oZ3$^(>>$K)J zV#AyX9#-V+N9mV9{83p9?!%hXb}Ht(cV{7q%(KrtJ-+*$`^WG9%ika0dEk5FCH3F+ zJ$uK21LusjHD1WJ!|iXVjdp|QQ$mMx!h3!YE_D&eAA3wpJeShG+L#l6`~fe(|B|qJ zssSdoRnB%`icIPmT7z+dneIYj^HyL3{&0~`mr#M-)=OC_r;b2mTolbJ48b?x%d}}* z0rBbIEi9VnS+h`{$cB#7O1;6U9JO;S1LPO6D(L(wuho>gSwH!$e6zf>A~&xAd@Wwf z1t*)qW=dv?+rqBF6I;N(=#O*6(ue6>03DkRpj9NcWF|`C0r$CTUuywRW}$0t)9_C` z+kh`ZNx;@TP6P{o1EN8i>L!|XoP=nwV@_R(p%}9sLeq}%n$9cd9z19K@-P3gzb3``z+cnye9KHldvm^LotvUS%lcXO0G0psltN1T7VqbXIysfEH(GUgL!96zXQ$CJ&c3;00z> z)ve-@^=Y3A#N>Vjj}Ycb8_x3>u@$&2l+(OqeLw zU#Jp&#OEH?@G5tmNV;BAOq^FASh3xGNjxrA**=pG4u2VT-q@<_N7U_N?B$FD;2oF2 zRh9rO*IamZNbkS|+5{ga%E~&zItci7upONNL;p$#TQ)F|y9X`DA?Bh_S1H{jk()XV zHYDdox*!|N=vwNxPOD8PvAD|f2_%Q*P-P#PaFj1-yQIEzDh1FH4_|OT=;f|Y>PmOZ zIiGy+;p1Q1SYJg_q3E%JEsFZ6JR9C@Fc}mOGvEO>7)P~{*uQU|Eg(R3QF)5>vC6zb za2XrFxQRSw?JIQdX0gFNI=*`Mo!&tBBrc%dT%BZNvZ0N`rI%hhZvD`$RBxO(eNs3! z!MnsLoo*5-i*!fiu#S)Oo+ngihr5141EWi>0>AYkM8bQ9NBcneokok z*fIjQReTawA68&o$kD5u%dRt7%X3g!+MhTfhOXE*kgvX$K2r790iJfEYBUupBM&`z z>PXD^$)8tVd3F5JAN`Rxjr+8L;DnA4SEbX`*i@c<2YMCvkA33fGL1$BwhGq zUcQT6V-8bE_0fLGwskok#HsOuQ`k}&JXHFzc>NSXwJUTM0%kK`^zozyzxC`Vbi~Ja z=E4jMs^^}2ZrpL_o#URb-#Z?B=pmI~7;Ec${C#jP!+dHo3Yynr)Z9fY{L%<>8~NhJjxVYKur!~9)kNV7LgnPm zCc(&2QjC?SsnUm{!|^P2^Ep*0&S?w10BzwmDgFug%7f~?g0DJEbpuQf(-Z^jRi4i- z+Koaq@0p-|Uh>(t%JhkjUE{XPr@pzM(YPgaX|}Kl;BS3h7GNWNc2&nTCoA6DPjVbPqL+0gYse?O@))4NY` zKzl2IXVyFC?cE|>@&q~#$%|tvO96zoGc!e=cm_A=st=bo^?l1Q4+-JC?S@MF?9bW9^eAoTNd@RZhU>=5^<;zFojK16gO8*HtV(0B zbVB8Px#R`!!JmSTMf=f~OeB*(^bNAH&@jgxJ37pYz08xykY zeMG2xymQT1qdPXphR)dVMOoR{>3Ts!uku!xc)%08u>vsSlgENUALw!2Y!?)i@<3U- z0~guC6KXDi$DX;x#8>txzq1M63TM6Yx;DYIO2VhZJtjcZ+_0OWcu6*gv>H6ndS~cP z56kojUkD4iWHT@TbYwud1n-Jo2&;Cshndg1l(nvf-G&UznKvetaXj!JdJQH6_!@*d zmh$1LeA^@CF06a82`0na^>dtTOMDt4EUt1lIDEv9O^CmrSt{|#-#e59ckM9cjhZmr z(fZogzdoLS_F2((X+tQw@ND`x>GH_+p7mYhM}O=`$DX~~bgRC6C-Rs!&in)pkSd`R zW4-YS;I}tS*2?4{9vm=$Ctgcv8hFv&-lf~PDo+634hYf)q`op|w90M*#id1UvULze zFv?=I$34T~a1v zyJ7%O-@*s(ls*5#^V$Ia@i=z$_*m!e8hX@k!hN1V9P+?if!L?cLPA-cWEMNBM4p#~*)keEr_9`{$SV&hd5ET{qtU z{`Xrh@n$j33E`Aq2>0!8eMgIu6V~OHA}9jB^Uda(JBZleyWH;94jR7MbLmu_IiRj&RTzu7D}N!h-`#KNltO;7z8CoB$-j&G6i z#UymVi#!E~ux-&k;t{Xam0aAX56}~U&>{GV8PRgFz)0)Ceby-6n8_{+RpRZhqbQ|s z_C>B|o_S_`_3p2ZJMOq^eEU1!9>@)E%@NkZ01THvF5RP&%2PC!H(Kx z`_i$=T#(oh$6Povi;}99c|{lAYrBThSw;fI3rtv4ELebqBr(JG49Y7$rhq3Y3OKXs zFiEtu4u>@fNr|>BCO{Q~+KT3Wr+kYk0T*8iN$P9~x^Da{7Hlqr52@&a)-mZ)iV7gQ z1EJ6SlSzGmbFTDsKA^IBXI%|eqq;I@V0YqCK3asb?5v`@X3FKa@&=F%R*s(NifZaF z84ti>4q*kRdRVvUyZR7)Cnjd#>-WCRwul|ggY67D$ zC!QStm!JDTkN@O9{@;&7JPPfnljx5f2P+Ur+Qx;iIPeJu%|sD&&a?8W=FIN9D*(^D2w3RB0g=S{A!r`+yZ9J`t*OV+re@~re#wfS(M52U)4?XbJo_#E;Q!E z;v;c}0*?3q#IE_sR*bRb^O0zbBiPtb!%LrPwUrQWZ=h8o@t&H$5G{|Z^Z6=t?93N{ z$_KSG^B5Q0z%Id?Xkt*5yi|*+R2U54O_YbHe4^Cr*p9z9x%?3?@`WdsT+HR&9_W2% z6TB5Ry&W1@#E77;Ogzd{G)v|Aa7SGNoiaGH(*bA{j^gdkorT$E`OuO=hEJ&nhcPe-Pey}vf)80&zQKq7<6CYt}-g+Gi$k2e+K)Ye;w06 zR3WiRn}N0t7+r?1Hv;;!on@RUhdSf+8Ao&oSGFi7Y{jp_iXX;-)(0`xWXQ{rSR{Yt zD_#ZLiS6*>-?ygHE{hEFSY@EtQ4_y0_7~zDO4Pj5+8?fIl zrVoj!L>m^_00PqMDX`i#b|VkYV?~W(SyU>ME2U;vzWSPE=92{k{i{#-sv46JvaW~5B|WLfW3Ry-G8`S;LU|tckG}~NuTl?Cl!~q-Q%Zz>Zis97hO0`Y9q<5 zVbcYCClfEkDv-TRClYK>Xd1Eyj8@>npuRr?-uFv}V9?9lThdq-mpRlC=?6c1vhcu3aaEy5ic;ZM|PUKei zICkXNxc1uX$0tAev9YG{#_tVt2iPsZd}WuzOCKQCr{&jKikIK2Zp*22PJ+t24+*Fu zc^(O-?&u)Z2VqIum%J@;ByL!CoeZ)npP|Mh^&iZr@1r7|=tNHP!kyM%+=vuAu;3uN>`{FJbUHY>CRpquFQ-X`@`4N9@?djVOG1PX1R7x^d#5uiSFaf>l|v5q7dkev6F7(zgB4Jf*;BUqGvQ&9cxe+bRkt zD0F?oM?A@<_jKE*RDhjgCzCl8Mu>s7VU`wE6D`+P#>3{)TZ4VDSP20nEllSSle}q0 zkW)53q^;~ok8c(+<)*+VE z0b}=fW>I`vf`zOfz0@|U$%STleY$Mh98GJSG}~^`OpXR*`OJkNvdU{5nMz(by9;gd z0ff(T^0>~au0L_$95lx#-nF%^Us0UsL%h7BB4I(lWG!Z+WVG{83KAyfa>;n}tiRmp z4Zhh986uQq%mQBE2AafWhOgQ)&z)mi)}?nX4dHIAXKS&HhXZ>JYwA?c0h? zpk!u~VW4a)WS}9agMn#}lqcnGuRFZTZ@l)#c=7oc#;Y&CGM;?miE-$SLt04ld~bAS z9wSajR=jku=;J3~9)9@Yu~P$Nr{crk>67_hCFd); zpUUx_VP13;e`7r!07Agq^7z3d;ye)UWtoZ4@+LKY3DFZtCYj~r5j)}NL!bO-<`93k zi$1z97J%n5$8Ub)8{^q$o*Dc0?(@Q!N5h$XUVrs9Es*h1I;@-tlycq(P0C*&?HBX$ zp}`Y(!CZH%b9_7$7d#NaHYX{4A!90Snn`w!t!>CYT9$bDxpJIGAUO%+Ki&#dDZYmZ z4|l^M#8=7ce{FqzJn`g{;}8Gv59Pp{V|^_bP}~lPTSR{NTTbHd@olamjA$);r6$H`Yx{^>JDn8|mgO;8zL7V+!5*2e3v9~yuB$6pxt zYr{f&3GU*aM2G3lfarQYPQ)p{}pf{%;~D?G*#yS`Hl z+Qb>mrW85H2ZWB+A5ew`w1-9%ByN?80GgP_AIe-XAcm5~2mQgzq9Tg~_^rw@;_>98 zM~{yqhmWf79v@d;Xo|LK1^e&KKZt?^g?pa1pv(I5S!^}O`bi++5bH+9n${X~QM z0{zl@X;#)lTbz+=qDHWB)-(u zB=NKu{TH0iGYBGII?~hdXHMO>@loIyD{XT0s<5Cpknc8b8OveAw)7!?{dli%-JW)# z^981r?VQV+E-i6<0?HJPvTrsz!&IDYF2oJ4XX!D-Wgo7W{5B6bVy=wwMQ>ifIOs~z z30;}FY$km=SdlVK2Xhc$Kk=u^OIwu*p8f@ma`godYwVkkBY3tH#W8{9lEK^rzVId> zB5p?!-N%cEgafXA3WGoMmP)`e?Rspt0d9p+l>7=Tl`Zm1C|RoFxCPPGehYxNZC1Yg zi=NhGZ7v&292_sAqoU%TuQ;Uav7v*Jef;>zaqhY2j;pS|((}R8Rs~s~v=#bB#cN?7 zd*n27D7g%|Sf&)&Xa-S8LF~INamnbN?Yn z8W-S|CHh_&^OIIigE!Xgn6-gNTE!wf=)eOr`rnp>PfUQ=^H+Vy3l9(LOwX67M-+XY zi{>)R*%bRv9)JW&F6ZGYzXMxf>x;3L!E)mYJOT9qZ|64y!AGX#>I4QS7^l^lDA6$8 z8H_C&1B9(#pgT-!h~4OE9m)m06`J9Pg|{uYjECyst1#dJdT8qbxvH-x0ACHWtaJ&L zjSd7BB&j2hB){^~3sytjd1UjPgXfIPuDHSjA^LSFPCfBp4}W-E^t<~U@AZhZHR;{zY~fMUYM0x7M!#lM{VvT<@FYy);gN6|~Sf<*Q3 z_cyTt9^2Lta4fuF0-JUMcx=@RdeNC5i1|}bKB0EIdmKJ;NSkx+(y2eIKJaiN;Ew*M zK6U#zc<#Y*{OFN!=bd+sM<0L8-~FWTy3P&{eOP*Bl9Qv|m995;Dx-fqpdPzyp9@My z$DZ}w*rj>%Q~5%NI7DefHV$`7eEO+;!L8I@X(Yfp2=+Cb(uars&PHlvAd7H$#kI zr)9#MY!PCQEa^g5^pn%aCL8Xr1zYk<$^ zg+{9s}O~~rda6<+d$~p z!dKF^TXVJhTrjxgJRkP2kMNQWsbd072xMGQj!Kx^B>)Eq{*s+-<{UzQRKbkmB3rV4 zM}_Ea1LUoORO3kVly4M7aQ3}Ha$ZM4Mnq{pxs?9oYypL(0{9RhKjY?g9IQ&4u5)$P zqE(h1*BF#=MBa4%sS<2}&#{Pwmwtp^{;qlFcY?Qodc~%gEQ@r&X|zGu9KS9vcsgrP z*}Y|frZH$4(cIaUcjph)kUVmIET|>xMs?>)gU`HxQsL5}YQRrCf(R5W^9v}yXPv-y zdAec%e`eLeZ`K~Qp;2!JfKigo1w~@PiA0hNWLT9ydi1c*JrsG|lB%EJ&XXq9Hi`_o zSm3i5!#E4==bnFlJpT9-+6?c`Bny-5vXKCeA3N&b1m-QNJkH5rwoe6SuZlon4|?c9}qrpIXnrH6`F$=8NKoPYvaEA zzBzX8OrP>&D3bC?NpS9Y=LuJR){RGhg?`c(B6#^hx94nmduSb`GNU}3s?9RclVYnO zvZUb26wW-YLw=gne*tOKXZRu?Sr$*J6H~rhG=E}UTic_>|8u^}>N}+@?8VES;oYL0 zmhVK069O`v^sl_?%JJzR|M9U?8^q%$k7LEQ0Bx|FUQ)c{@87V9N*d8zkmO@?Y0k(3og9SPdnUw_ub*8*MTOhb;0A+dHkS^ zT?hn&JXRUK6WctVyruGD@e=DGoO_I%s25fQ;YBxepLf@!+!${!EXk zH|^lyRSLdH{+wiFqj4;N=&!b~eC(N#e;+WLpEe^edM`FIJkIiO2)};lh%bI!e90x_ zfBPT(N8_*mwg1=nZ~o@r82^X=-Jc#8oOf`%@!BinwO3vqhu(O@{ohyMvFA|L0;WOv z_Lsa-I@sSk4#g_z;5m>Xt`%Fm1}-^6)2zes4A@rLwDK02Y&D`%d?Fqy_o5DxG3FPz zJ;aI*^R5DHeasMEw}bjIV%fA6Rpcc<^;v>10+n6B`W0X>@Vadm`ANR;q|JlzNj*3U zR;a^yaHhtmW>$Tp9~OAR>llNlSVsf$%W^3cKYbY}J%Y5AvzuTQ={O+LdgGAF4?bgeS%48Gv)dZ{QfM_-JHUdBBBl#EfdiNGl5!fQJGX|dqQByl#20fR;T5gYhtJI0`c za@Z{*-b5wmUZac%2XjNPLY16#5SLh2zB%53CD6MnOP~_0RaoMRw;F4P#?Rcwr~zo) z#Gb{kGW>UA(D*eG6lRm^&{lAkow(~L^aLshF--ys1wk#DXB~kht>h=%vRpXoK-Q`J zRXQyW7c}_6GvW2X>bpf*EYXR@ymSS5a2lAr>?-wvAxxe+q>rnMUik6HV3AzzoSo(G z^WOi!1K!-h&X{57vuNYHz@!&nbkTU%wb$gkn}D4ntvVIhx^;KmP*@IkDlTYNLW+zh#v!Q$Fp$B{sfV(%) zm>7v2KXCuS4}NG|e#PbfnH=ja;89rai2AMEMzlYans4T>O4MeL6dH9V1vm3LbOtgN z%Q_NQ@lu?4&;y_&d`)#-I|hZr9_0;f;(0`#elu@ylJebIHo%|#*Pk6HcuCN%HDMJS z@zG!Cce!&0R((wU=EfUu7@xZRb}azdkaAMzyK;Ff6d&lL_|T7u+THSr{>tOI=rZ7M z`HT(sXX)b3^zmcI#^*lwxpD6|?sc0I)8;|<$rH!N<(FMPe)PwFY+Qc%m2Sr`eBle@ z!S8)Y#M9RJpHSM4G@XFo121}+xSN=J_z8}GXA`tc|K)Sn#ZpMRmh z^JSOC!`LQ{ynQ`yQQBLER;^$MTdoRgeSZlnb(3tuko_!09uFe zE>g~6y^4t!4s<=yq61vYCMZRogLYx~I0B}}|9mbtN03ocWl|sdOeTO20)7vg-*@Jv zSl-ZbaZ!d?ys{yFK@)JznWDO)DdXQ88~(PXMT`K3eA7JBw|JFrX}6ECWrb#azk=FH!Wn{;Dy zqAjHseE4LRi4Tz0&AQAd9^pNIH9sl;RVKwJY)2-%P>aQ73#Bk+J-$hV!@fyH!<*1t zoS@6LXO4hnNu3YgNwO0T*i_XOn0%dh$W-AigC(RLj?8P18K<&XXA;MSl{G>PFOV8p>-H}(?2j_b+ zd#$sO0l*^xblhype5J4Pa_X>w-Yvt2*5R!T{4!UW^G+*+n$&@!t1?Fe8 zbUo3b6t$H3Z&nHgQ%v50EpXN=uOF$lO0yCERiM#fm;*ZVZiO`V_B8Ol5kNkjj}9K7 zopNFTE4yAG08F~%+b;RJGXmCKt-qc1=&r(B!e%?b=5m8?-6ktw((+@MhSEzexnvwTaA2IYP1NzK zn%tq&R?aUcdgPJE#sd#N;7wlM0$e`mpUo_b^iO{LW7cy*3pnbSfi4=4Gm0O581&<; z0v33@)Q9Z?_-?^WLdCQK9k(CUmzK2fX7Swm!<#xRb!75Mwfvz__G2wT+Qt2Yt8vQn zX4l6aeRO=|-g`=`KDm3Y7_rg1@rE15tsnk~zbg&ZFMh(NjIgNPwL9B3$8ze^O8|#2 z^yBsy-(8HHA$K^lF@#QEfaa;Kp!7@7ygW*3opA9{wsgeBj4MA$;NM-1Jbj{lwygWB zbV-gjM(5h@_3_kGPmj<4@#p>hUcVI_N7PqIco|S^>R);};lJm-H;oV9_R+y(&Uq6d zwmDR$ugDJHu_ngZ7;^z)HwthWN8Bc^lm5JzsJL}^qW?bg^fTj*FMWBu{`%`<&)&V| zgNX9Y-}zL#-1MFs$NS%Zi{I{yozH6n{P+`(Ssvi-f5w??NS^Nl`L3iQuyLFhc;!h4 zz>hsaImt%oxa)Y!2X4uCJ5QcUc=25-sds*#SOw{r`i6jdd6THaJSYvpF`Cn$BPAe1 z+$CU~eD_>Io_?cD``C7=6o1V{z2NhkjVq>B>?-TSJ1tO6!}I7hUGhN?GulWPwN?BD zCtDaGm{ph9M=yfN3Xehfj28%(3!t=h^rn_NWXmz4ZemZo(8}DV{s$X&NoWKkq=QfE zq8*5Ny*VEc4?pAOxmhB1Nj$`s3nHi9%FTXM{UJbkcx zea$xb{oy;m`c=O<{kso5;3q`(?%C&y96Vvd+Gy!27p z4*b;!v6-8XDHC0;lk|J68(qv*Z^ou`j9Dw1edxG5p7;`^c~-!>!`p1cA@&#pEx(Yn zk4l6pSKb~luC1m7?c-M1>>{wzZve}a5nk@n+(!-_(z@-~`0d~Nt#R<&^Zb>WlROTs zbBTYGTsm6MX5XVKx*X3$R-YM%f$mgrqd4kTF?lzk2WFJaCR zKA&MMtkO{O(&-mp!G{dC1?jV7GEXAwz7J}OM}Qn-%k!*k*#LfutaHR9Jj6z!t zhin#mbaHbm=rrcU3*LQxBACVgfwRvZ zS6_2YI=BW4FWUk904BP096EexeD!O0d()OXX0nBS+DJ^?op{fUH;x)wZEk96?cc{iUtw zN6Kh5Gli~r>27X62Sxm}Zx{lg^~ZOjpL^!n@wv}_PJJwKLZ9O!9?z|gxq7qul>W!f zH{U$ocgy?j!)Z=5)`y?8*YJ0tPO87`*|S&XIRREb6fsqmKXwxjR1z|6M@i<*e`8b?PhswK@LSM?XH^`@Z-2`|?DOHz51%!io_u-13HIhc-J% z5+@~zf$U_>TPnNa7cePM8xU65!I4ei3TR(+NP~3}Ow4G^W6nCj(NDN& z7npg8bQ!R7(PLb>0I&c9+wEd;DR=u=KKRV}rI(I30pk=O7%}m;@vZ}S<8WHMY8!7H z&4L^xbfdRyiP)Rq%#GpYkL!~x6i|sj>941>am~-hrN2pF@&h#)7yL%}&a-%Xw`l04 zj_A<`{h#`}j`%ElZu?z3eHZz$#~&Ye-0`LH&2QZ|9(?d2KR(ZerJdrVzwYEKDeAw> zGt4>b^+Gkf;f}xXNvUI2V~%Q7)mH(e#fkwLe1k^plvs7CZE(C0p@5hZ7?qKnfqV-h zpu_7)=w;V2ClxGhI4j@dd_ltI4=-A)?@k~*e;r?=badZgj?O}_WZ)rR>D-T0gp70) z*jCe)I*r*RJL#>w=TC%`&tllUEIjZE^0_^j*DARvQ+-vzn&!-cEZFgyAPeDkAX71J zzi8L8YrV+{!s~W$>?uaJ>*ikGdK&0s=&Yh`sbmw?zK$g_Od|@1bu<1LBTWNUeq|mI z4rlTo9Sz1?v7quRu#Ao9t`r9eyv<)Y(*wA&VryGy9r(Gl)i_{P$K*nxJ;x?1$T|$3 zmtJ^r+@y8YKl+FNz&9y)d6r+Ir`Y+aGxO7i&a8mj2|ZPgg)X%N_}e}T%PH8V3hos$A;*zD7&5S2I=yCpytzbi;~q5IU@_gTa01zI3bgIWZqY{K(nd& z<7hz%zEL z7(ZPKV&a{F`dF6>ly#JEw#|o#Tri^!l(QBt50TfnLw?dEo8*``-`NCjg}D`o(%S{M zhBFaMTlnw`XVQcMI#>~aO5IS-mmsjIXqNh3p>$OjR5vo3c!xO+!F zn+?$z&{`Ps5-k?LKD0QPPj*!!d@(39wF!M;B5VTbwT=R_@e%%RYBZpacAgf70?%XW z%GN>G5H0C;fj!Mjs#Tov`?V_XHK9>)MrX}&_O$TV}C<1r+c@%gbG+%S)}KGgnJ@_&d1=51!+n zLb~RfYyDy@#>X9Zer0^`;fLLKeWA#HSN(m+Ks~3%;#k_OAH9BpK>U1N;PByNY_=rF;#Kva?vdj}gHn-Xj5tuVJ;pa<%P01#qyYZ(CGI!|!vTjk2$FeI zaiSe;*K~BI%mH|T4%KCRPrs!SOTCO?zct&uSQj4OsBEn20LlmIFyW+IS?g7%JgHd0 z!-7DdY}#+un=-x$=deURN7~+FxAjWQ8(`#xw|KJpAdVbH$>r0|ID8q zfAi=6`uMB=)qgeq^q>CIuB9EIDX7-DCmRqmK9`9R4b9!5Nhr zZ>~f0>yP<1PjMK9lFsNzU0feyS{MFPsxmTEMPo4cp0XheOly0F;V# zYBHl|S)WH#^!!=q%!dF7j&7HfVf7l3L+5_Cc^hc66K~GlA?ri`dFr8Pn#a8+b~_2{ zv}M|EpiRUUd^#E_@VQ!zHIIFLz@j?RAM-ug^4nsmd+Wfo*W^_RuX*7&2Ap#C%R)lJ z3lyFXW>Lm|@$_Nelq*{RS*l1Mn99zOCnm~^#KjlN^wCphm}PR_3xMN78@_JtRqsHc zdXpoZ?Aw9jokbQwuapL!8J+otrU+*<@hF|4qCTfES;5SJ(j| zR;4JNNzW3RCwfNrs>KVBkZ+INFF0U4t}u z+prJX*f7yU7tQR=539@m5Jbl+EX&d7oRX=(cp{122A6D4{V2@gr!1NWJN2L{7Jwd^ zHp2;vP43fAJ~f_r{IRijk2X}b_(TtnF~0A8?;GcweZVI;guL;Ct~~LzK5(jUPbxe* z8LOR^!Rc7S0#`oHJRQeav@VkT> z;slPLPcn~VEDKaBX4G$Y`-N8gG}D6*JmgI}BzlH_7ECsHiQ6^TUOPVh6F)J|-ha0B z(XapbkN^vm=TrCmZzgd)>s^Z$yR;SvqobpB2*mrsF~$JPihaZu;z!g6gp)wdQ3UY_vPC=*r6bCdzhmW@J zmjwn=cZ2;Rkz(pre+Uy}(8T=Yi4ARRkEl<*Id1*Xt>Z8Lg}*TV`~U9mjKB3a|Hk;q z+izDt-RsTp3oksI@01Jh!*-Mc_~JHlC5%YIAB?k8re&OWoN4dSyuobVt~Vd_jSev~ zN+G*GfbZ^A)^$zXaRao}LNLz#x4S$X_cHb-|7)<^AS_DPg4G)W#-{1&B{^^^rCj6 zH57jGobrOn?b&rSiS{yK0=F;y!3DETWsdf@+uXMNZ-Vo!&b$*ECJyQHBD}|Ljul?B z3cuO8W-v5!k^qGzV%8tnTn4t{sBPL`y5fvn$y`Tw#w|;fn5R1vz;&$h#~k94nE0Ad z`5TYjsu$|D74#czhC@8y?NF*}T7%LSar_jDG^_b#faE^re(vOqd z46U#8;dK0UfOjN0XTf1yX(=Dun31_yuPdYr=9`F?H$+x^*Hp~ z0oXV=*-};m&>))N2yPbM+?68OG&-FwX$BA-ow9P>;gqsr3mIK*#yXg38V4X7Ju}R_ zKKVzHjwP@19stUhuKs?pC*B6KlizK#9r>Ys@#1KC~8dAp#T=++BD^6;OQ4z;c0qH__k;ybMSwD4r}#tWWKoj5-J=yRVP zuOB+31@EprzNA0yn)2r0pZLk2lrS%c+Rg5^>H<)2>V{7s<)d@t+Ygc!NShk(W3F#> z%rT};?xW6d@CbIt%S6Xu=?h@?Db50+iJv!PE=$gvsJ>fWV>d*(%A>!#{iyvP{HuR8 zjvYDVpA}l!2&g{T<^=xcn;YZ!@e|{=58pQ4ufD^}!SWl4`R(XEd-r(rn(to98e-+N zO}b1!=WdtepsBAZ%4)My_LY9lMV>d_czt}~3t!Ua`~_{w*%0$R^j-1=c}w`Gt8RSv zP3gaq`wxzv{u4hr zF1q-_v7wEPzc)k-kWskZ_iy@SipP%f=;S-jXosz&7QE!CF;M-@{A9u6Q|c0%@<6`yQzWtNS}LDfI?HjI zCjcno8y+ZM{#kYj_<)SZfxvli=&t&T!7=vNJCKhKYqK9@=E%oZ@kN2m&_+C&M45d0 z4YITo7aXlxfPC(FMT=XL%k38JcnaryxNOr|>7`#fq{?fqaSU|u81(wu&ar2makXPS z``okR?yuc5zIyjp$6a@Qbv*OTb7Nh7_29vS+NiJF7G_)>`FNJ*C_j}Vog3;$^a=YQ zGVQ}-_SgZ>Z&fpXHvIHQ{DF(7E;vu~h+!|H5+C&o?70q*i8=Yi4kT`HH^XhEx;WyJ zb>H-PN*w5lpt7QHu?aLC!Wu-eGvwp@w6T*MJrW!;yge6vaRlx_w{OhoLuKQL5$y25 zsL$>dD|CI>76oX+=k8Mgyz2mu+R2M>;f$xA;4E+MsyqE**6~(gIn<~4)=;s>ch75Q zkTsiVjd$Jfv134e;_w7%r-0QqPqP)dbwOjy9D}RXHZO4k&Yep0VvZm+a-^ADoWqqq4A^n4Nm6Q+*yMpoGX#~@>b|0 zT3>AF9C_l{(eZbG@$ZiJzwZ`bT=$bts$L$1rk;rlU=N7v9FTvvfLf}eF_`M6F0R9b z1IVZyIUmur?GFd@hWM&^+@1_m~g%ff}BO(um^nVHVN@(gy)#|2(rVIMGm-jU;;Cq`0b6SvI?WViL4`;Wij!@6C;_FFL6gZ4+7dV*&H)H5b0~ zIP_-tH`)ZR=ILZapM;MkZ0bba;3)ELgh8YJQ?p}Z5J>2I7(K4`Hlg+4$ag);SCQ(e-I&Y%6rv=iGf(0IC*@W zI(bT);C*7#CRiKWd+xbseDA>rwJ2Tp1{hf;8{j8y|A}$I#g~l3M-C4j1y3Ai*gC;c zamktu|DjbK-MEw?F7^EX+57Wg%dRWE6Whql_i_RfGcgbYK@bxG5G1OK69|GVRuyZo zTe7>W|8VqVOX29Y)NV(pExAG+ZcA!gC3RGhMU`4oh1-(alA|NK|8j?0sw#>z32+1{ z4#f!ohXOH=IlT8WUnczhzHhB_&V88)0xVEcx3KQrXYalCn)cem+54Px&lPUs0Z242 z&~fYX=|Wj_5t9@DlvW}gDPn464=a7kC*bWHk3{C@k3U-;tq=l}dGV{I@0)ySh~Yu3jFfU>}LB8#y^{V@UEe)M08cu5ie zb$s``?;hv!(zz3PV>-T@E}jwDO_GYQDW~2GoH<~^0W#eSNw=3EV&pgcVi? zWRj6Ct24h4iqdadFcNB^WG6v`-@05W(ORzsmxHJ(IFnU*@i!j1{rI{W%FobxL8Y|w z@>BobGJG7AX1o~8kQiZ8-#0R4mfLyCNW>p5qa(t{$8?&DG-h}^_}+c{EMr~iHJ)-f zxji0#{PFRn`|ltBzkl*i#&^E+opJ2grspljD*c&p!k8ePi^Zyu=6@b(&)7-*7=P3q zoSRHIE+~S|?+_`+#~Mfm*{6Cz+Rzuy+(wdPpH>~x;RWJxy;!W`PoX%+FuK}JJHhSl zHi>L7_{b4_Aq&`dX}<=iphYbi#g;N<6q~5vbV8%&Jn03_>BLh?JhAoc5Lz9jzoj)y zYJNgUzr_w`EbmNUpJS^&ZmX^ zLeT^*i*FRihvp-vc=jo{;C(TzXfl4QWQG1Gf!Htu`N*@q1#O>gR?;e+mi`*g{nH)@ z{CI2AftlD&(CW7w2Z*~Nlki|CcGlhI#vedqV1~= zNh>%V+SD`atKf>DY)uMK`u$)i@S|>Ql71=NX$MVIBZ7&}t7pTu!JGPa| z=%f!O39u1nP3H4|pEFBFhPiOgt6tX9tz3+zs8J zj2Buf$c7!VCX%!1fFMM(9ZTAUjy}nsRn`)gwn4A3M4bT`s=c7Z6fYoHu(Vwkvp8W$ zAXop79X*-_yj^n2k7Qna@x|lv%PzBv*vw?YsDUF+?i%wbC>uWH@pe)_uBkN35f)5W zz4oorsMu4xvG$t0eG3kJxD+ zD?k$>jz^CkvyaF*A|(VqEx!0?@A|&+)vtYReB&G6@J1fsZ><<#yxfR-q~_Qvr7UV>A48JO zFptXeyBhv;_`2(^9l!Vszu@07pV&Gc+ZA#VMsmbs|B}Fdp(IL)_&Sv}{7fgJBZ>V2rT!t<%LZvU8Ns;=v^g5c=DL@$^ zk}IEfa8b1Zyh_-QD)Z<~fqB|f_90*9S?4)MdW%gKqR;@y==N$G(nmrzQvw!XnD7={ zFr_J7&`$bv~H)0!#DG5W>GrrW@acG**R-@-Yb0L) zWeqK~_|5AmGA&n7@*}Ho6R){+q;4|~vaEN25;}#zL|zH_`B)EQ#nAd*9@v)2hS_FY zV0FRSPfiz&%4~((A}Ck6`WPP*`Iy|Ra5~Jh+SFlQ3gCSf=#^bIjLKRRC*c(uW#*14 zP`G2JU?FyfAft0h+xdpJV~IN(z^mXBr@~T{aZ8|ZapcRQ z09_zS^Cc}IQwLWuiyvN^LZPwp1sjq5TAb7A*~qaFao08ri|1YAp@$wCn;XYmA3_#E zxdXs|sGfi5yz%<$udh3P85)t%wr3OdQef4u^oL9dGqgRGf6w0run-v&0F*JZrVn=|VVK)ywC&F1Y6S`*eW!f4G+gvE+G78K zy<^`#7R!lADEWY~nuZ>T9@>7<{ zUm$h6a_1HsZocWJ@$PrO+Z)suPI9+;j~{XW!WX|dzIgwayqVq2Ustgak$s#%*`%}K z;RNilAoF@-z=8$SfQ_Ta#!WX%{yle_))${-to?{fUFoh2L$^5vRA-U3FK9ROsn`N& zzifoLaEo{06Vhe&6(3@usJFp!1ld;(@Pb2E)0X^}K>-S?tYOZE-vSINX#UR6cDU6P z>8RrAq5!&FcW8Cg!D9{)w0XHLdP+w5p+y(6Nphf^Bz=+8#Gg-*I5t?h6PE4Jk7XKN zJZxZXaN#Xrxd0M)aVm_n$g@VFh?!^EP!=tW5#eB)goq71p3dCMScwMiqB3ipkR4l^ zZw?0qKzWoHvUSs07`@K?_jaYvb~0)6l1**}&V+lp5F3*wTDgl`z)-{<*Rkyal$`h#95szXd{J#e^OmzBg4R*q z7wJm2A$iLc%qr9ORAf$ngaC(q4*CFnBVY#nkB|zk&?^K>SyMW3_urk6F_3iuCb!+; zx1*djP_&{Wn_L3#rnu#ew~Re1_WLIAN6E@L^9+E_R|-6^TAmG6zHBAJ9?*>|+YCaf z)t!t^r_H=8y)lfVi4W(B7qQ22SAV~R&bVB!SadF z$NWYi>mmV3`1I{{q0di6n{p1VE1u~795A!mk+l+aXj)Sy`EsFz zgxwIsW^-o7^t9AEg)qk_ufmz(Cwv?lP?}EQmIF_`D085=JH3F|jaPBQBA+C3mc8I? z01u&QI}f0f(6V;Y?t~>TAYRvxMa)9hRA)M(vY-_+T$Y^?@FEBnXq-=ieL@Cb=%GWH zJ2x^^|7V|l+HZFbjW%uC6t8Qez(&BoWfeAm-y>e}aQA_~{rS?D?$-c4;Y|f6P7es_ zwPqdeeDj;fWtU&6iJApdm#M&}pkLZ{?G~PV1DVyjof%|{>6Wzc66SVrpJ1cub_P`L zdRMyi#XZpCAAT<)yd38V0$-UScO&du*ot?S!(GH(?)pv|}sSWKo$&LYn$U=uv)kdfFr8Crl(DltDH(h6-==AlQZIz%J)CjvNoq&vG zQ`RMs7c+ao|AO!6v*2*vn>YpK)mz-QCyyT=fAIUiKOTMT5p5{dgU5C6Z5OT2MZfIoG>XUm$XOg5i9dBTrruJg#U z7W)rA_|Ulb-g|As+HT=km`kABMDqE2qFZjhIV$aoU4G2;t6%-<_}u3|ZyEkiR(xDG z;!=%_xqh%#%m&yCYSBOc{NeG&TW%S5-~BH6Zacgxiwp_De<-GIC|@=qc%Pw)1`MS3 z19dmbWT7S20XxCCjg$~=e5E|J^d%9nAWgeAP?wz4jb(m<*4(KZX)iXQpuWvs#a`qJ z@*DTuP45dAq;0qL)|l%#&$1APY?WJZwBqN`Az5HrYy}m4mJh*FFWeT;PK^y-U?`q` z$4lR&UztQl^B`9nQqh7xRW`;%$xsZ5+nn}+&wZ4v>HrQ}i>4f1u!7(lTWH_lAr5U- z$?a%aLZuiTqPHEP=MnWtLkg@2SD9%n+2!;({z7SuzA4@xJ^IM__$NL-?)}WYe$wH{ z;Ui=J!GnIs0sVLPt~HCXp7N*rH1Zgu@-y#$@Oen%BlSR+DDWqB5RZQwd{SkWCI0e_ z5|eE{X({I8-<_Ys{7qRqR7oh%C0e@&dGH~IgYud|Vz2Vpi7xwtG6hdTX8<@j#Lvzt zJ^Ofq5G>MsWv`6@-!aLZv=A$hc0P4B2`CdT0a|-|1)$rBds!gA^QkG+ekt_npfX!P z+mbFCr)9X;2T*jnWi0A$6nQ{6qfsiH=hMoY8r#BVy)4W5M+);GLc!&g=Vvx9EPc!= zzR0Y?v>iVF7YW#pp@Eo5o>XA+qii;1H-I4Z48LkHaneG1fJ>Qb`(=?g}jEdQH(7zpn#?St(e`nfV&h z)U>tyCs`S%E^&F{rM$)w!A!!3%2(Qb1v<|z0`lmA3>$Z>Tiy55&%%*SWS{?F^jgIk z7{i?Q2TNi?FQD}U-G7_^rT6EI$@Y!7SMvsW8A4LH-SFbMEB10fyJ0I|}i%Wr^=uskG~JCfWkB6uFY}0SNrSf?NgO6uDf7X#psC zh}P=;`wu=aocZ8{u~;@baZM-}#nt z`I1@Rs9R2KlP%aqtYA!Ml;D@jp=+OnX9nSn2A_VA z^qiNbpqA{?4<2O3F28}@&ST9G`$WJ=O=$&Q4E5k3{#eS0-K0eaGE<}bNfutHBs#$jK@wixiHUG_V071JL{fr4H#a>6%OfwIK& z0xWvz^GP>t0%Ma!tK1k|>5SZ1n3oJSfBJ*Pm|wK67dZ|TF6$e>)(~XOwVhLa^@%oc zib=w6c}mm1pqwGmn=SCA3$`A^_?No14EQ{LWAD_2#>J2L#updFmko3H-M4K6ywQ&u z_|5Hv#vVSmUQ8ejy~#z7jlzqDIhYK0g1Kn7v9U28`0j(_v!DOm_~^$zR_}@6H~o9Z zy2dasx7)LeH>T4k7UM^DZJ*k4-H`J$1FC@g z(m5=~X^V@$QdvdDDd~2{K6olv7X(cQUI4$~Om`5&3yEZrgND0q(jTsZ(iO1_9>zGf z>RW0;s}EH*k1I%F>xY;^@N-_rR~GQmYAs>~ibyEf3=GH4t_uJT8s$?5G67eILdyv~ z5q;aUP0u|pEUB6b^tKQ=h+36U51kVlLHmD z0nWu~jP0_u#4lB1G@FHfI=~k~cW$l#c!UFOb_t_eoKLp5x5t0~-~IRFyz>qX{sxUP zc|vP8#<!boviDCTLO7ZgppiC-LMUkk8JQFBu_m!mfb7iQFvSH|U96PCT&0 zoe7q*ck(Y~oDI%WwzSzKsZ;8bj+w5VcusZ4j);lJGRX6o-7al1HvNbkcYG;_XaD~F zM6fyg}a{UXY#fk8Z-=yHPKvq&Fi!%5{_2SsMk3ti#aw< z+nT(2`!A31xF#Y=on8!VM3R$FmjLd}_{guUWK5gk6`jpL_Ziepn_fnCQVyBL6p0wy z*~oFX5WjfiW51jlM~@vDS6_40xa0Oa#>o@;?WbQXrcD_yN6O}o_CXJ_?6i_i$mV2e zzXLpE6`RgD_$@J#q@%0m9-`@S>-S^xxuDkwv|5iK2r`+HF=o{bg ze;V_j!F|^@k0{}BEjI80D%DT0opFONkj*B6$E%MXJ~Hln%Ui}f-u^b@xj=&dxPXAJ zEPz}I+r`HqRG;{*WP-WPbD~zpi_`cu^v>!FfB73a%S;|OG(j4gDw<%8u33KprlE&=xeVHj z!QdCP1+k~J)n*EPpzKGFClhk0IP}nwwOnY+hiyaZAFy20!QV34kF<}e5~Op+!OJlh zSI{9V)z7rh6*ezfOR#+TkN!uWHXzQFE^?~-)3)YdUdDEO`-IXLd@WXF`x%i1b`mcW$fOTa!?Vdb!ppT%P z{zYi3FwmY8X6nknbQ5jWDV!aUg98oj2*0Uvl8bL81vH zZe4(>MMt}~NhKn3tt)BQmws0WsW~ntV2kOCjAV^Tp6DDtUZJQO$qIWOhD`{hn@7I4Fa zCZXl;geC6Bl`r+3i57rnr(I{GJsTANi*=-lL>;siSaj9+WFD}b%-L`R&%h^E;Op}e z3zIAij~+hkg^V(Yv-)$-JvT2{F$P^343Rg+55E6>>(5oHEXcSUM=^{33(mi2>|5XO zO`s=Z*C~r37Hxa?uKWLCxx;3rh%I=L`Ww0&rWM8)fmJ%{vD)u?5hAFh&7xQdP~Paf zq_|wxn4!(guJK)M_?~$3ah1t0@+mslu&uA}9dCKdoo*L%v^nw(cShZo_(=tsa6=I3 z)xNg3%hJD1Q8swOE{>cWW*KHRF6Aj}A0(YX5juLo0Dt&w0%jH-{eJY>X)sV?S0sJ< zlb;?BKKR|SUT?P4O`;z+d;l&-Ln-M-I zPi?zz`-&+GC_$PX=STJ1nn#;yrcfBi% z3GNWf2ize$xc|WT&bPla?z{KCvBxLL8cPz%~85}M5eo1xeP)-p&M zl&Z0ByqzQzwlAo10YzoVopcF@Tyn-C!%`}s8~>=>cBUP}uizNFs*MB@9eZb53Q}$Y zY$cX>`j^dsLB7RjeNHHmp*7w)j7@By^-!i{)0m%HHB{rE2wRn!>fjvushiq|9h<>M zRd+0$$iq#Vi-|(`G0#%oN92fQqD@7kjWW_Yc;kg=>{Y3Q%?6o^EgPHKobn<$g_h{* zlNK@U4$v>TfWTjr@z#FcCQVw{@$B=@k7JT^Y-7_jcfRG#<3IV2|NQu!-~R3KH~+@p z7=QXt|EY24(82Na)6b0Oo_p5g*NaPaxZUUMmIU--9r~2gMrb#_p+tG`I@l&^;X2x? z@a4liDZC4y7fy7(^Gk)w|KX$;Dt1!kY`iS9{A?TAx60a~`tp2V6j&CJc1CaTfb~>4 za;I3q?J|*~QyJrxt%5FYR=_yRfGlm*VWC>tInxvkOERlnLA(su!D~Ir+XvJIr230T zy9#rmAmGR0SH{i)RIS*H4C|zsMMmSNZVvw%HxmJ#ZWc?ng1$X^5LhB z;JwBX(qqp=u`9B&_9&@87Ho>bEGnEGM~{;cUkt`IJ_SyR+Hn9sgsg3~SnA&PPQqV> zC7kg$!8FR$=o649R0o`ZiIkIT(ss6?X`8R)G6}eKUM?(Uk#1dt7t?zt+7~Hj^EjPE zcFJm4$fAR-)CZg*%UGtBtlkW{eI{S9!SJ0d9+#Ca)c@#*KO9Gn9gap54?oJhZy*16 z8#x4ucJ0|U9(nlD@%68Bx05@7*dn?0xHac03?ed9jh;Z9 zd6|H$oxG{@il6Nh9qc=$h46$|>EIy(sx9!H%XOI2(9ri5lazoWCR`p(`p8EJ+VI%W3x}>- zWD!z#v!W=K4Vbp_U3X+GNGAQ(6BG+#FNK^}S<(2>N}o)U=aJ(teD3q(%U}M=SlhSP z3uND=QZaYP*Y~cE&0`yWGL1)_*?|7iFa4tM`?Rs-F)rjI@6ZK!fypP7D|vD|dew@$z|t^9m-P z?LB7#zw|EZ6^}n0hb6KrR2YRp+yb8&E0XO72@aU!l(Q; zo(o7k`fMLsF8xuu#K8FB;t+~?0>f=pcJAG?t_?GfYQ8X@fA0D5+0TD|eBzUz7~lBD zH~r>!o|s^4!@RbZr;MU=+jgUmH?m`A-eQY=sjr_9Qn`&LCL)7f@=dv2AZGcY`{+F=vpgqN;}Jci6VkA0x3m& z=&MS5ZgHeS&)X?)C);Pt1qg8;E}*>Zn*FGpg4+xnwm2!dC^sNO`3ZLBUk)^{lsI62 z>FG{lz)#pJ(4kCC2EKeJ$i;AMhLEVnMFTi}=*v8b@#v2p9v}F?2gZA~zBtSiWk~aQ zkQ{unQvU|z?Zmx;fFD+Tuz)mJsfUKpegr7Mx5S-Z_!-{-<_8$lNo6h6JivlaY5S4+ z%q|fv>jBSE&;}RVBg5wlc*#!qhMJR&LoVqOq`dpB8+$?pmLdSl?ZSp-{dL6FWgmEn z(B`hNmQ9gqL{Q)~4w<7fDqX^162y@5PZ=A8CKo>yJ+ap<(4QLDzUELeufhaB_QhC} z$8fM)DVVtcT*@VJAFY~T75l@PJ1R^?N}{k=FQ@5wxMG}cT#YT=a}-9 z1)6Ewu0R%n;95q-KD(GvP_c2R)3)s0R7ux%pGCg9uy2gfz9yViGcg|v?LGoR1ici%X6PsYVA6QOZz{axqD#g* z-g#FZd$k0(02V1p

~m3DIf2&POXS58Q^Cb_NIt)V_%+Z(3kk9-8^YT(ruNN2mGh z9|#2Hi*9EoJT}2!{NfkJ4}S3dvA(`$Kl(A)QsYeT=xSj~@wB zNiQ4&?OXD)*B4ACBNRG~9420j0jFRd1twUN!cQLR(D?2M@=XAMCmo$8PX%4Z$Nh#_ zw&ZI4($6pWk>dxx``z)ekA2K_VNs0;7TMe*iZ0nI-V@poo_FrS@yoybtA6s}1dCF$l-9p8*0hqx5ngswby`M!q?`M1$nNdX9IJ>cWt>ak>6YS2?Uk#7cboLWkcuw zj#%;Yzs}$P-uK2I{<9DJab@mc`wpf)8`_AoLEguvolPx$14ist%1M3Li1K$@{08`L zjfeh^Z2C`{LVPtIjj*Mur>pMvi9kn&@N%j$PK50z_Y;tal3U!q;JI6=v}Jd>X!&&e z_DQ?v1)wjmq%DjRU`zK=LKQfokHH_jd051mE{h82Qb*+CH$W00kv>|?rOuO(4T!{7 z&PImE;8ch7!SoxF(1tEJLKfl^km)*IgpP`-VeGOiu-AT3-~xivVS%jMDM#?)j|&CCW(`0; z1ij$*p*)U$XYm7^3=uUSYc(X>g$2I5XN zkTY$;vJ|%g;EZ?uW@_`IjFbr|b3)8Y;}ip)5Wed`=eL~1a70YwNh;0P1p$v6#ip2O zDc5K#9~i2vNto{_>%7Ur=6+3`A_}BS3wC-yc?&U8U?%gPl73#e*w86rY+Kd?E^}I+ zVk;*hS+npZp|fRV@h#{Iz`KR3yjfujs^kcG>f^Z1MZfp={_eQp#v8}cWA#J^eiVeK z=*TAJbZf`?{n{1m7f~m(MMh-`JkJ=J{=BpN6#)tLPs=oZEnazI+f#0} z1*wP&Tz@6iv(&%9K_omf;FE7m&W9qAWB;q0;4{PAlg31(Mi@E?jxxZL zAhB~0%=Brd zxo4mC?>G6~m_agpN64dw#qk)|z5aTo$w#JjIZaM&F_i_k3NsGA@B;X{k`rW-YM9%z z`oc8v7o($;?Gy&9?}j)eKP?WLpnw`3KfxUpayoHpll1Vze>{Hlqldi-gazGPsXcV) z(75@A8~xaA_oL{a`y_eaHQ+nhmDu@40i+d{eHU=8mi2WxI>0Nyr#SNKB!E2@11?7g zm6_dbTZ>ib38qOL2%h@z$Tu(1`Pj!lp3SMuVY8fGts8@)g9|kI-L9ys zj>x9p^Jwxz4?ZwHu8llx?4JctM>HTq{K(^X!@K~_exZ7dD+R_EoSH^MyQM{e<8qJeGsjW`@lv;4*A+fikKyDC(HD64v^= zKP+g=25^34UAWdY)sqaoj*$vofLsa`O*RCOL%C^eQ3H8sp^;pQptU~QO_>g%GzWRg z0LVZ$zj~ZTRcM;ubtt(`_!zmNRWM8GX?}xfGzP$>tN^*j1MQ#IZ;X%Tw~WHt=Ss=m zmS+1&!0d23e|QQf8j>!79yFUQD<_cU(Na2@dIYf;DEHGT)6+ZPphkvh=p$A{5?eFQ z@)r5pVDqyC<>}j7+Rz?8azy8k6XV*euk|C+zw^NljKB3eA9DJli!U0_JpI&o{Lx3p zR$ct#&NBKKcZ@YQ*3$SFu{yReh7!kDRY%&NKurH}ir>^HvveEEp# z#_#b>1IfwH1<5CdKN9poR?993Wpuj8qQcjuJ0T?0X=k}h7U48?FA3mT;ghJ;Vg}Rn z!9~%>9I^yF#;4is5A)6WW(Djg_jP?}8-2jJsuhSV0$EN4l0sfm@lSY{zCxuhqBM8N z7tn}B!NeXu^D1&qaq1O&_+WL@5uBG@uI~g@X4x|>0-Mg#Iv-TP`J!<-;u(_@Iyi)T za+Ds`nG5XKTyxF1;)*MMk*Vb~?#-tIuE{2@1TA3UMg!R$s2y;+jF$&CD#;1lqY65; zqyeYAjSb%8Wrc46(78Yd`>NCMF7lSwG0`$#dVHK=?srA2Fws=PoD zNRnTc?}Qd*TH<718i>j3e=DHJgrDqOzZpVTim)$Of05;nkd_1)1UgWh%&V{yG_nO# z=R6(G-1s1S(Xk3?q{O5gD?xChE*hd~=T3LJ%yhueHOyHOOBr+lszjLeoZguh@_Lau z(Uc9&>qOy22hjM)jymCFb69ndAL*9Kqa!kaHBLI30g=Lbps$uf>{>_;cfk0I79PXp zH(QA3QPcA;x={4ISmn4EvaX?IozSBH!G|6Uzh&twIbMtid>8oQOU5Oyc}?!B8LGZZ zuz(~_2V^O%^byiK<)psZdv@lhir#NpA>yLkx|1SggXiRAr#O$_CdVq3w(| z$i!dvBg68MYkd3>*3x19geAa(CnR6Zx9y7{>PIFGtz{7N;rD;M(O5{{82i*yPmfP% z1I)(5i*K>;me;aSS$$N-w)O~)v7Va29 zz5FP%)C-A=K&;7gt~^Rt=f`r5Y(+xuLVa>=T4V>(hh(z7#H zpg{ddIPl#@^xx)-Z$yu1(;>Ih3NQ%3c{r<_4;Q#Bk2VvI3w&Ffo07D9{LGu*JbvRZ z{>AZk{`P-0{)_+OuZ{o3ul=fh@%Uqpj%S~Hb{x^hnK_V)NPhb}ccz&`s3uO3UTk)4 zZGg(8JTGxn&W{XWQ|#+Drm)laAf@r1#ZYe|>~=Ew252lA-!-_tp|no{#nxM47Sp=o z6YAXU-L~!omlK$~RA=UCk6Rw!X3oYJ$SbnQD4~K*?UYTvL-WpD*iszT#+>(Ui~TrL zlMLmOTTrx<@5w?-dM5QeN!w91Q%$a?&sE*T2wUa?_~S>AiD!Y)rvz<5?DlP6R4~Axtc_O;uhYRhO_KQrJ7{_#>fm&ObUo-*VH9i7IVAx5&0-`K` zycnFOvz*fSjw2~$fmqTdX&cIvFTK-x;cUR9*0j(m^aXk3Ag;9`mi2=yD?I=g(wRS@ z4bJ|rV15N!1V0k~Brw_X5@4x|T(9k$)*pN+40H`1Cdvlm zQm0;p(;??}_g$Q{VRFPKqt6WSB-NtMHWSxd1d*;4NPP z8P6VmZX7;(*pGYKXZl=p;e~#b4PM{Xq{C~%;fno}Pd+i8dFE*qF-Ukgg8zcmhM*=? z%y`2a-e7sLkpRr~^Vkm|*(|4DB&M80d^p>yO_r0M z-c$^2%J5I(p^Yss4U0S$cF!N?@1^)d0=&Y-g_Gm8S6tz{;@e{9HS&IyJTcT5W4i(*ZQ*1?LrO9knZj6-uAeJcH~|Ys@JO&4et(8clL$j>9szC?D*ia9E@nW0 z-NBhw{3l=79-LG7Tdn7wf8PHEj4#;qpE|M46S)#6-Rh^lS|7)Xb@zDhdwzagbm=9& zqt1pho1hu8XfK-pElAL56agDC)+G2MeS+>4J5$78xtycG-QaC48t?-bcx;L2@GCa* zLHxEhtoMK6{%nl30iyc$0gE~HA^r!|vdLQmeM>S#6RG^A)5f^;;!DQ+-~WqwG~Op( z>=TH^T@etU?Wq10|3K2dR=FzVHccZLXIUk~5$(H+TF@Bc!I#s@R%L#%*wUZWnGYE0 z0_ZQzB!I;9ves1|1UWI{PDi` z{lfUmfB7$u|JOhGug7ov#$Ot@-+uex@4`5TaF=*<Vedy3)dMj>Rg6S%~6G9zm&gPpX1SXeFXxX5+JaJmu{jLVGR(!Y$zE-JLR1LmQ@7e@8Huv zf&=Y9x@dx-J!%jxz%=kCD?rgw8G@F4DRX}+blYGVkjo#Y@}c^k3+WfFDg73JKdC=C zc$`e>gcpO@_2cPwg2~}kg2>AajTt`7?^JWTm_(7fQLEscD9L5~Kml#L#-3cJ6<)4= z|GEHwm+D3jl-KOsC9Wn7K1EB^jo*AeIX2tGKSMVrFw>n0a>7YN&OAm=jKpUW()22G z@oe*4wg8twdnOttuN^!^hc76j&b>(O$uaA@8r^0GNrFj}WG2mCXu!lB;3pq{a-7=M zz^)0Hm!4d7(S^RU4{#UEYgeg;_lJM{gXkl#a%9EFFZk}>WtY8XyymjYiXV!u;|yt8 z63ezb15A@N@^?aX65?y}7)H={5Rw^H}uwAeIbU)7V)coHjy@yh}<=Y%Gv~?!7dTe->pX&_d)NP*f2)F?@9m`7=XvR zY;Wj7MZH4Tc3HM*(_U>u(y>>W$am3_w$LP}P<_<^ZESFNvxqJgqGgz_<(Bgd&~`X8 z^!%K(B{@CWV@&L|qzNY|{gWM327h7$C`U8DKQ$MbR*;{H+g+ zzwy_9bNrb<^Jm75H(ozZ9^dlc#qrl+TgQ)k{25$#$+zA3o<0`6q|T^3LHg3Mo00pLq- zjG@z^A|29C2rXhMD)>bmmP!Sw@@$LaNuXpaPjV;NUiZN;_V}q@8=%Z|=`Z-YMFSM4 zk5Ql0?Ue8S2NxfyOeinPEA94&3t2V371SA1Ee#yP|M}%oq#>I zNum2yw`F`ZryCz5cR)9^z?))X(^XH|Q<%I79YI|D?d=5_;nx~!%*Wz98&0Q9Roy_PWj#EV|W z|D0dplY!VVH%*r}J$_u!pA9DYFA)~>i*9jNc)8-2059y+6Tf&}s!zHg*Z|FmE%6=w z3xXgQu4SNFCO8LpQu>nW@~#`e!W$%CEje|BRtFT{Yy%Lwn6NA>JYXS8Q;(KWMTSZL=@YQou&2&Nu~&GDY(8+D zU@|c>QTR?GLA;(G74zaC?%3Hv(Qj*`+;y;0(e(GuQ=EMfU?zR5U z)ZFR1@rD~rkJhuoiW3Es-8=AxGtq);{8Eo_e9LX7awfF4YiV0WZuyeyyOr1%7D4Fe z1z~WhBWy{Zf5G|ViYqRcAF?<*aPYu*`#aw`F1+XxZ-RUgqV7H#Y+RDl02(mnVBh4q(ucupSb83;8MmNt+s)MNK%68Q%X3Xo0IKc zZT3I?iBF7&fB1v3zP4_i)-6UBr1Ul3h|Pxg`NK!YTi$%5Ua9(n3M2f|?3aPwp~_aBLmhkl&Bzu}yt;seke!EBY~DPRT?MHt^fTHTC8D z@Bh;H`nSF@cCYV|s?sIX=oj3X;?ZZ@242VTX3U%;+1y3u34vexwO{jJE%D+n>H}f> zm#l4fJ~*)6h+1~xMTqU81BGwM>x+M(t+F1g23Xzp79kqsR)N4W1(dfOW6K|8d;S1# ze&|!+boxh?nFs8QcXTE|uIGwC>Z7q?eaYKyVh{@1@Gb>L7fP_kADE1aegdUQ>M->$ zM2cPxGX*+K$s)TKpBiVvLY##Gtnh}mgj5>(!YLrrwC<|}oJ<)Yym3tnYsNG{Jz6F> zWRalXgAErSH=J_C@6s;Qrv!F7d>kYf-mIN z*y4gIztQJE-@U+F6a3HoHt)Phx#?_tfow>bBzgf%Ws!|1Qweee zXxo3JCwvLCpUm6%0634qlH1UAm|#cNAYA)1LMjxkqvlh*914r%nE|0?FKsb_(jHb- zM~W7uf|fjE?HAdX9u;u^n&yzXq;bCBZUiB?^o<2TXZoZ=jBy0DmzyqaWqyLw!Y@Jj zpxSnPx+EgKnoqF~&C=zKcfnM+3bdI%Zu>$3OO6R&G!tHlq;)JCtqnT&fyt68R{&2` zLU_{b!V51P*IttsnEC>|V#a8sW1B3jCRj-Pmk(z$rR!UI81K-)GS z^8smvi6wo5u1FiEfE51XTm*mU43YsZW503GOafmPETjawQ43tYih4yM`gN3&)OEGK zbG<4ilCyGQihP$hZTW&P?sh&tdlgQHv%DSJGhKy-IM=JtmGm^K3!3K)Vi%3TCa|+P z>CmY~qQ+&hPQG!ONMKi<*s|$16sio`g&l1{=J%pYQcwfP8SxU)Q<$Jc&jP$9KnJ}C zTb-;uC|yc6cEBDv%9|CtxdPAcO@mHdx*mjVP7vX%>LNV8xiKDl^kF|Hx@XVcaoJ^; z`LA7&2ahKS`G&vM_~IA8I1V2^>;-=o#`!JR$rGov;n*72Tz&Pp^DTFdtrI*hstuAh z1(SJ#_z(zY#s|o|{#8c;3odVdM1@8k5=z_Q0P3d*pOz5Uz1ziCmw|9{Ocs6?;%xRJ z8?`Z3tt1(zh?S=}8$r=fAb)~q1IogR`ooq@(y8(6v(MNU7hZUY|8w&sj}D$AKVb{D zA@C$GW#T1J$k(D$GFU|VKZUUmLIZlKgJR1EPhY~!t}~Y9H^$(}FZ(VPpx?!3;Nmxc z>NI_PJcEl+0h3rLP2U7~>opfqc8z`70Du1TpC9*r_A_Ju{sZopT-9bV%u9H5Ru(Px zoijGI$i3r^w~V*H^KJ6cw!~wn%43N5@JAk?#sIgqR8D#o+aLaG848pZL9U2%7kBsg z-h&U02OoIA|HI3j_#1AyN&WH~Z(e(xG2W$BlC){nBAULy?~}jtoo|niee9!tbSy56 zUG^b7)U9k?LXS!8;4bhl|I+)%^>4U7ce%x9t6>wbTiEpw!e81?dHYJ_TJW!^;L%TF z>%cSN4WDR*i+jMU51B5syWFN4tBfJZbsrQe{=|1s6+ICMNYr1?ImIK+LRwztM$btA zXs5B9a-~h%<%_gn92Nc&kw$rVj5`cW6GL@Bf`;wxyooDo=w0{E&!Ve{ys z6C8y^B6S7VI+T&H7x;Zk^$+()@$j<(is{c0VMfa!9WP2=6}caZHg;nVDW&~5ba>qk zvdee;^^u~C2lQ%u+G6Yxo!@Uj`v^sMo1PLtgXoFzm*q(ZV_FB7F@Nw=1;*`TPdqWc z_=V4puYc{IkNdy!yfB^&dlXu2(E@8~K$X8^Y;^%FnR z7%x1VBdqPhLG}p5%qCQ2DjXltgrCwjG9aQ6Kn;k>?f{ z!A}(3NNwm;Bo)AGR()vODn&->7ThG>ZNr>cMGZpaB2wt(+Ve9t|6CDAII4)6s)V(Z|run9sJbiigHc`mrb z#yJmtuLUTggySjvia4_75tMB$qc676Z+P#6+gUX91wz(R&_smWi@bl!7IF4#l!nfS z-Q&6EpY{KDf8e)%Yi#Mf!_SbmwT|1r{~!b+jvscP!`s=ZC%MQqASi~u2*8Izg(ZEb zZH(Zoa=;U4Bxsd(w2;*x8)LCXg^K;eiD|H5Zo{l|D{UO-b%AK9=iEQw$Jd!NVWGq@ zB?@m+kObsVg3j>Hcx*F5Y0h2Hq&;VR(y=j6MZzU+XuPXI27-zjPLox!Svuaq^W$Ju z<}8VB(rDc0w2N7%Dam=K2i_xhG}r~n<-BGLRoe;5PiiQ+xXuv76&X7jG<>LN!6HuCB<*)Jx8*5T$Bxf zuO?crCHQXdBab{hzV@}Rt@tII+*4ZYZ+O%5uDkE{Un_CtA6xpaTZ8LvJ7Vt&Oj+zp z`*U5SmHS^>6>uZ?cer313j()G>H3q$#bYH%|O44!IJ` z-E=s);w@5dW<{X2{R_UcZauC~+7Vf9Lv$$Ot~y$?xTh2%@mp85gDGIC`oO62q=oCr zA6j%9-&_IvPxAc{x)+1=Z7OCd5(anVH| zlgc3XZ5N-?LV2(M^Y^|_f7*-G-D|sj0fGw=zxWHkpv5$QWwfO+KfI`>E)m3EI_()x zKk?-FAAkR!cyms__1IAG-FuA2@9{4#OKR?Gvnc>f1;Fs1#Ien(n5>;&H$d=gfCst(qCK`>P4AwL{0%a z>!6s6KFd0k{`g#d4|$RsTzKr8(r3IFnUA3D`NS8KO0M;K!7hGO(-$;9(*^u<7W_yb zp#5w+{z5)1lFYw)MHM1lZW^VzvpYS)T(+<=_ER2=BM)yeVg}41vl%D0w#T~W3FZJU zSgrB@!y0e=fA^Q}|HAl#KlnqPbH1+giN?JQV2rP8o}qp$koS1A6hFAVYAjM8zkA_K zfD6kGcsY^X-bG_KX9_yL|q4*Mizaj z3B!W*H0ZJ^hOzl7Y1>J+6uT^>< zmvcDc%2jSbYoLeFqa33M+guW1QwCV- zn(GjmnONI$aMmpVmqE9rR}P#9^f~_D)#%ayEqWHK(DITj0*|rnJ8-V(_Glu_ipM{K zFEQKO+vB0{J!IKzijc8Kn+#-PHyek`F28)7fByOAN49@MYI|Z65c4XZOu3@#?2Pd< z6ur>JV#s1MwC%5n)-dBTc!`y@Um`0w=n|Y1y%+OJ<-FB0m60Al3SRn%D1{_-(85j| zM>dcAPR?|bK8TzQtvFfKBu#yg6dBf7GL0xe27GKdTn5gwRyNU1>v}=w53Meo{FOV# z!m0htFCDfET~KPp3chXK<}q&D)iP0$h0or->*EP6RzLdjkNeSK-p0&kIWJgaalGvX zHd`Okl@ z?BK3Z?lkdO^!D+*$cl|OeVP8?3W|!07Dt|cethavpZ4zy*${)re*0QFu&-YPWWNbG zdb3Qq7Q#o5936MP^R98n9e0e)t>ZqqU_WOoM}y$6s0sf^EvZ@Y0N913dcC{-C#FZbaD}O*B&l} ziEEK{r33X5B;t2AN;%j&baQn ztF4PCZ8kKfkDu5Q&!&CBi+_C4jh{lWP_>Oxg-KPT=musV+a@QM^__VpAPa5b!*4br zgR2rBXPt?cK+85b)!CH{e6p!N#`M^InXuB1N|Ng~)FEL9c$~Wky2Pn$+gCW-SZNZZ zgGsv4rcK#YZkdQp9Lm(0GM~59I35R}G$%q~I}~UGvqI}~G8SPv2M(tJ$RaclH(}w< z%s7)3V4eGq=(|tYK0vhC*O2pX?DpEF>^5KN!;g{a0?Wu6VP11Emu%~td3^hXpN_cg z)?399JT$a1K0^*E&Uuq<;3{o#jsB@aY=2oWv84X1GGw^39D<+cR-nrPD%t+a+!Nmb z$POX>2S1rg2d7I$(mnn_x+Ps+B!Zb9Xbmp~s!7fYJIhfMD`q`EPR33MZ`Po>xJKU# zq)$@b6>4gsMcY_XPMfyNQkuS~Tob?E>6u zXrx6MIOB`2%8==f0X?!Tw{c-HebE_j){3WmcpEaX6u>pT5-oSK-E6|?3vRNxV?jHnWLgf$_u>kB{f;F=&2= z1+WHWL&NW1c?|ZJn{M`t%NxJF<6#xl(Bf!hYeIWA?pTsc`NF3&pl`Q$YvA8 zBAj&e8aUBO7W_OWOnKX55{jEvK$3iZV})$WsH2OOPmC48fgo@~gcm%^4b++%$A zPYKfIl?^j>P>^sI(>!i(1G-|RGg%#~44XLdv+3oxhHPSaA_4z!B^_gVS=avk`+OIe zjqKii2lD^dvfA~~BK^4R`|uxpcs%*!Q@JZ`Khj=o$oEL*asPiYV4aL5)s45Nd&4eU zHZ_)RzWL^H`|Y=RF%Q3p&BF!&;J3kfduP=P8=@@rar-DOJ9}KZbC8oQevD3E`wF!E z0IJ&1v7!(uh|Ztr;D|}?115|Q&}D(WLN0ou?l0ieZs1H59Db(Uv>@R{E&&?&85@a> zN1Z>$SVrb9LfI=i%H79Z7ZXFC0M&#yLeNrmEE{cJv3fZ&}IDW2lR1~YCdN)4f>#@zrh?o1w`u){GwMXV#DvT?-&rS>Y4x`wfd0( zos|@??U?eh6Uh$eRDUC_0%UN(hrd7z4$VB1k&P~6Km5qim=un42ro)xo-eV2kqODx_VzfcjV@#F#v5-OfA-J(@5bNy(1*rv{np=h2RRRh|u4>;Vxz7lhWFf{3tB=HXlPu#z=0 zavCga2Ta|l(*paLyb4lIPKil)jk5wuUksYktWK3YV6rJvGOv(MK9o&EQG8-kaHyf_ z@VAQ0{rfq0*`%qjruuv;}ANFLc*-sOhQUNdYQjLVM6z5rx&&ws2?cPgf0Nm z1r;|m4rqMWS0zGqy_Q@6dHagRkih)`oNWlsY2+}!mLBL*h4fXxK6WZNzpY(?8QQoM z2^iDb2p>N_F2C%uapmP#jN>}5@Z<&OmsDS#l#BfvVU0snc1)#z z9JCW(0_lsxs-2mO!IobD*Q*sNF8^m@q>Q<>sVVDnScT`S5UhG=`Dupa({`lgWr*QR ziG$mlRFI~bOnHR>aj%3(>M_ZZk#n7ERLRdvJ!wknjZY^|!^B$P(pS3T|1$!HXC+?_ z;N@NwVw^1WKd9rg^3VNBttNsCUg6DNoaCl%2_+71D1eso2+th7RJ8a7@F zTI#@^pMt5Afb;V{OWFdPp?dLX6k>&lZDiUmoQ%X(dD@o0(BW=oRDmZ^?F>x3 zB&F9I63UkKhrjP~Vy7ZcVwEmP8s|7Gh%N`~Bi4yi6^feT=cG)e{=tiI?)}WC#v_mX zXzbm)7SGFHEJEo+ZhzTxQk%yEd-siZ-+j;6xBq}In&kIsXyGoA(sJ@H>{MHxvxk>c zt-0RWoXv)_VDfK-%$|1OrEbTL9T}he)F%}mvmXJt_^mH}_r{xVa(}04Y?^b$Tq9F~ zI)3KUpBYa)`NY_@#$tY3TH_n8vRjturcGQec2o;3+_k`0-)GZ)!G-6KyY9Zr8)W-S zH1XLvMlJ;K=};_6f4 z52eZ}vq|w+7~!Wtey8J_+CmJyiKtv`vXPAob@$Df7degF2|MvLW9k^Yrju%rvC?)R zRcYUaSAbS2<5dUO%XJXoL)!sf{g?5i9Ns`ZF+MjbQccUEQT+}=(9Df;As))J5SFz8|;)FUxpXuc}zTgc)HNR z2f0>O$_nIj&?4#jPBH~%UBI$=@yk>%fm6zx z#APLu5A9I%S5X?e9=-YX`KIiN==3R)ynEv6tFIXsU39UZZh}rNH~1F>4D$8gs z^){41T^F#kLN6I4tDW*<&`w;@L%RLF6V6r^T>HEK#>!P%fkvpj=KA2^U)msuLluW- zIaYnaWkon`l{@NY6A%4~aq2c)k^<1tb}s@uS&+DFoy7L`XLp;8z!aBCZ<5}N*eq>Gg$m4cnNe=oR*0bz?bf53tIa%1#$eu2ekJW z5TasiC;vJl%L$5CkA(7eYldyBV}G#YQw_sw0I-*m%j8RFLtN{ zvF~hhl~MXmYBPM#yWceqU2xGjaUvHXnDn@#%%C`MaKBKJw^AupLpr=UU%=%51uYbF z3P>)+@zo5oe3v7tGdtu4)i`7P=(sm?TEJ#QqXH&y`&>b>+2w!Vh4jP$F8*tMpy9*E z&pr42xKNv^ER1g(OV~-U6=5HGC2RhlW&=*hX#LSzb z-}g(u zF-w?zrJN1$oj>z)$|BQ+o~QA}nl`=n-~Z)t-+lLKfz5A(sjPr{BE$6%h&G%8$`GX{ zV8hJgnJj+(^q>AW{I_5l680zlvmdGBwvZk>%1frJOS@Sr?F~J&3RSncuXKU%YCLal zs>sy=H}$0eew+9qQj*AB**KSorfrx+3X*bLxG#jl7eug2z5o%8_=Qphm7_9!Nm*zS zQfYKVt}KzRVn(sjSVvN{O4HjXAG=&%MbS~T zqFUC0BKSh91L<<0X_WvAP;Oid3KXsR%p@D=M}*haLu4O`C-sJ0d8!PpQ97h3w3SKQmkda-L3ZVi zePqP9jnfyovc?gHn20nr5l- zBerk<{;~hS0bi7(4*<4QGJFxjx{Pt?>lI)O(i>Bk_5^Q#=u4hHWJ{GHpK4NQYJn)G zZ2S{RLE2wc?vg4pNkROogarj>`zq7qOE$}mQp21IoiVnhl1@>=_*Bk*cWacZ+U^CA zb-zP^$~DJL?Z1GT6Ui!vBrL8QV3ZKKK;vR#J#RY$F;oo^(x@_b0^>_|nJ0)P&^oV! zNtAXwDigBV;z_P)gEdXdAX)KLSUlDRk>!SnxeIU(#(bTm-_SREgYVP4usl@}jLH~K znk!Cf;5_^E)8pU%xBl(%7yeKG$vC>fJ2vw3BWQg=oz}B(&E&4AvX-6k@INic41o_4 zfX2<3_^F_L|KkCgaGG36dcZ8T#Y7){a_YCt4+~n3bDyc$iAD+v4_);*L6ys9%hoqG z*qDjCsb2~prn=G@!FojC{sx`vME?R^jOr?Vv1U2GxoBzoS+@xXmNiXDFpdBAOkeus z>n=S+(W|h4IxE?Ai!cL@45nisbY_!F(;!tk6H!nJK4Nxir))PcJZg31BHajjBia|qI+L^j_tVHp%+4XO^ zx?Hs0kRsQ@z(}5O4?p}cq6E-t30IGI_9Jhvz3R$w!37ui&Ku=$!s{1CsUlwBfmzrE zWWz^2Vpimb8)POJ@{Kno1&R}e#LOfrT9iAMO(qn#dtT&b11{dlE*8zPhjMIV0qHv- z-BbeVPhGc99+%wE*)NOV-q^3=Vd6M=@IX|!h(zlP^u>jiWth^mN9;tj<%2g_c#eB+L1PY`pGA~apW=i*ggChz3-w{TSL#4 z>UZAtu5su6O;`%^#yMsVgMZ-g*u z7t^{g6uyMv6Kr&wV=H6MB~2MxQx~Fbvxo?uWjI$SH}VcM5A-StF3gc*dS^o$r2B-& zLgNjsYtB#nYADy4Jar3!q4^Vqr$rb?5U%Y)f>EYb0wOCZsB}}C(t1mt%N3S9P&dAz z?3$pn6J6v&=e|$`ZYkj>zbJ}dD&w}K&%sYSBck|=1z_y746Jtz^!40@I1Wz8GqC#Y z>S>e~6aLtO4OxuOp5%?alv$VL0<9A|$mhJ(7k%UvfQ9rTadHck+#y0&iI(s}(SAu=-Sl%IaDV7EYU>jk|2;W(g;G3dt9w@q9kvgFb z${_$-ps_G0LKQyn3bVi$hsnURLt0?Ayw?)JMQ4jin^dN3v?UWk)vvNk0EG`@xpMIA zAaz=J;u)WQFvDpat6&ARQ#5t!k2;=)yS?mr7?%-Ktn zLIAua$R(|JvO#@OwlPm|5hp}kw9SA0y05A)P?qwOr;&5h`JIhKMw%Lv;(L$y|qNa1Y z&fQHGIb~B5zC@U0oCT;ulUO&g(>X`E9sp&^Par0*lP7yBjXZ^TqQ(#kCc0N)3G*yt zz*9S0>`XX8Ioc=iMLErh^X={xr&n50H(K}w&WFbxqVY>GzS27&^pTN;jbNfx72Po` zVj*KeH!WObgC@6W-H%SYXs1ko8*w!SQO>Ld-WEU?!;?2C!+rQ>ofb9~L zUUbe*kOy6rx-xA{V3N}^mxY2Z4;q_DM?M>@0Cz|bfllg7U~s3Nk%9b_v1#H2#M_X0 zjGVB(wq`%F`SVHE)rdZL33Q8n`_@4SVp00;3^}1vwrF#KZ6mfUC;A|Oj=;iLII~ek zx@poEjH@=CHR%_cubRj!tD<=3>f=mv*6CN&4M4zVVIm!yo=I{;fJ= z&DQ3o^xiz)B>lWqHvY*~bhfs;_fYQ_#%DfruP+4gXm>6K$S}#?mVs>Q8Cu-6^J7BP z%(f_oPV^hcj*U0ne*3sxn{77y_^tbE+YXMHHg=jODSw(KDM5G|oOEIJTx5`S$%0T2 zy#do83R{(!e2y*Pm7j1BVpmArze`)WGmj2hz@w+4X661t=zlSh~Fvk1BkT&6VrW2&>j_9Ci1UB~KE z-PTnhCoPX`*Gn?+!ID31GkGe$txWm?Fys1M<2-g^7dY8#66Zr4yC79LHYmVDHa^l< z`b>>3@gmw6CPDg1C*9JN=^@$HozDa*u6nj&sjDZ@mBgzdZihU;C@$ z@BHoG9sk$=>@SaZyzOniL-w>b#Qbc5|7%Aa*S*+Ga1KN;x|qiRx3Ti}7dF_L;1b(> z4h;xQk!i`=X4*#yLI{GNF0{4`m})AUW7JRx`36=Mj#lbI;e|1;%D|~?sxx>cjo%4pz)kh2L`>45*WbcZG(;I?u5%(w_h{|Po@zSqOxJ>MCE4=wm;kFP^JL;5D* zwp5073UnrCJQprMB`eyB8(PQNe7dSKv@Z#ug;#-fU+f|wTU_McNPz-S#N>%c$uG9c zMkLT5`Se`$Dy)JZhfZUrBdpFu_%aQV?wHQ!7X?6DW#AKXXENym%9p)Dd2<*QeB_hW z(ef7QkO-#48D$z8H7gLLUbDW=FZg%D#Gn{iNrlH{!2#KD>NL%rG|F6FOd@1p*+=4G zvBcoQ#r|!P=vcH82aT z4L95{j&Jdwx5$qyPr&Z|Nb0u5=1RFJ8S2L-qyh9Po#dIzv4`J*<}X}ChcxKDVS#|S zWU!zyuJnP2Uq<&p=D$+0&7xg#rR*ncKt3{D6H@@B;6TQcPdqVx_=6vgBU*f2e);9& z+H0@&oy2qOGl@E>jj!6oiwo=3r{w0Y46;jp=?#d#P&2-1;p@d9^`H)ljHo*J$ihgl zkQ*t`&p49Yjl~u(+JvV)@RfBTMF>y$d>we?d5rr$`#C>CytcNt zRo7lKe(l$OO+35&=nOu$>99Cb0v^TKmy1A|bitZV^8G}O=M=KQiNt{m^a=RM))?kvSnz^{J98>7GU#V?J|e*W`gzc$n8b3l*mIL2LT<@fH{ z>pqV@`aho&JOQ8$KQDm024rRUM`_YoLCWwGE_Y7reA(gZ-*3 z{Vww;HqzE=GoEDOe5i5FPkHEn`}VHcuUPh-Z-00E;fH^JeD=Q2jRzil&^W&wPyLp; znxAYiFL(i)O30ROb95RdyA+hc7Ta33PyJnZ()bZl0GjE%sY8oO0(>artMaYBrYEl$ zT>L_Y90ceoK(6r1eCR4$apw)CBiObJgn|nEd;CWEP_}}nui4%Jwl%HmNSVIo;s9?b zek?SV*#uMH64(a)9Zy^3?d$1BJjKB2^vIFt#v5LL{rJ7#`#rx@ z6XCFA+)19>DC3)PvRmV12CRwds?NWnFt>fcUaYVRs!CwdMlT9>_{4Qapp^4=ev-~X z?PK}#yu|+)}%ydw<9F1uhI@P(00siP4g1#a#nyh_M8=P@roJrozhD`vJG=P z@N}HlGU{LU3w0=iWjzSVgU7@MxUaqR+#h4ezkZN)3eLn?6OaiajW1_9C|wf;X<|=U zOHfbD2hee6x$>Mm5!D^b6go^Dt&Q>`Yn2x8hI4|_VOk^+NH^p}?vu4gi7@Do)(IDY z2ECD!g^Tz_pL(_p)Gvd?Viddp06e2Qk)t{y`grV_|Efidw!fCgMum-=?}%9zUZtzn zi9mEL`k#F2Nnb(dPFW95czMhjxrfd@Z(R4f*ZX&w^8zA|NP9BI2SU?=0opFXq{fq{ z4zbNXW78{p;(Ph5aKLnNgcF8&gYQY-=C?jYDQA%)+F+yFu~Oh2L5$60e6%cUQ4#)l zN<`>1_B);a>pp-!DrKL%F!t|XAK%yJ|4U!G zzxo3t#b4N=${NwzK1?v5`j&me2}OB?3-7is*#MKq z{{8#Mcfb4H@wv}^){6q#1^X#Gv2|h`(Bk&z-uiQ9KdH^CMM;tSi!$mV;myx5V?S-@#uc86M)@Dc_uO;0U&O`94_d0|U_Ykc zy3G~beQgYQS1aBCr$7nDEZf+Gg2p-4mwNaSW9QL}zUZf)+m(RzNhY=zxV?<0#1DL1 z4x%PJ{Im%&L12H&fG#QPf;94>Rf%YQF{3}|LzZYuJXAW7>S#p?sSBZ{6BDq4sAw#N zSYOdLF1D*3D3A@yy0|?oTLF2LDQyleoGI-^zs~M5)v{v`3G&U8)BNI~B9&S0gmF92 zS1Ko2vH*U3)Ab?Ge5KDcFYp!K{MgiV#bdnFN|pcPBIM0cbN1k~z`-xL0#*t&2@jJis!SPrB%KvTr{5_hR z#QXen&yAypkBno-jt>4`)yfs(x8axW@fQ4PeyfjZI4Fr6`_3H)Ui=h0-In;V+XqX9(DDrMDDBUJ&Lkb|-dXodB@n;a3W?bG1iUh~qY4DZ z6%CL&fOqyZX!g@Ue6UPx5+JP!=1GZZcE~_x=H|Hd zw%dFG7Jel7XrCdw=3I+YFIE2}y#(}4_5LYkXjg#Tb<)M#?h#C+j}7kCqr$Eq`^dvWgng2lJ`kVoqZ zu%NX5_%!tj6)NJ7)D`dv2Oj4HO-m9#>1$ms1dIrgpz8{x##KZCq?9Z0cRpSilMx;k z20L~9<~P4-G;cfg8&Bn{2OoSu^xLMT?*1Q5Ww75ekyPo_sUU&{@ht+ffFfpboA!-g zL@NMi7UhX80@*a2U>4uHMPUBmg2cMg#dxwT;faahfl3)J`M|+T!XAJ8iSdz-eAFjh z_Z`upbvJY>hyDd^fY~7b!ux+|TzJt%?jsHH0n%)hZD9`1Lbz-&o`d?&_DR2R&6_2o z^8n&N9ls{%haP&+FKOd9fBc^>ZNRwXzeU&g?HliS=R3!N1LsbClB?(}B4@&o zAT#xpOruohMWJLP9(!#cMaZJ>$}VNC-8L(?B4Y;spEJc12cj&@=|t3vI%teQCLt`P ze34Ld7(Rd#n^N=DI&|K1LZccgKci)d`lY$2GU`yaNrvlVoJ)jT(2}stg064T1DS&+ zg3wr2=lQB8LWBbn=p!TT1%+^+oDU7U9V-vOhP_?Zbr5!@^@>dXqt1wgPH7%-<|ip@ z>v{XS-!!fB4;$M}g=5+b^S5;eHD~<%`+k1>6>Wt7n}7HZ$A9`4{?qZMH{IrW<;Zh~ z$C2j``)3}^;oB!QkJl#08xhS%jC=nUv+6>K{WiuarwdY#*c^WZPhz5)_!^Lz`c3o# zQ$b5Y_?>JfT`-iVixH@H>-Ib#yslY=)3G}+ z<|jl6M?zC!Q>nKh)+qoF*e45-DUPQiIh3}$=v)u=r_7mPT0;nsk-9aev{hZ3x|ErA z!U>QMhBInN#BcrS^EnSuz>{%Wf2qj--LLYuz3pw*6*k68&Zf{>i}+%OV%B3OY&}j! z*G~yt*GbtK;7t9^W4!V3R(LTvf}MKo!b($=@?hpVLxjJ3u9+b;@~6c{Hgr&iT{zg4 z^4quzWw1>8P5J`!NKqJvEtK0oMyk~IDYOi9OJ9rL2|L@(vL?BOd@+!Zp_@qIQ{?(7 z70ctB=qgI3$!E@QD$v4FUz;Ub#Z6(H&%emFWM#9Kx8kzdx#o4(WV5ScyFxlygy&INHpg7SRMLxymX8cUn85#9`fBThiw}SB zgCF_@E9ahjP#b?P6tGZdvmd*tH~%S1U9g0!JoF1L9K?sBp89CoLI}{d0smlLE>y61 zby4I|pgdNAw%t{RtXz12I_(qR&3+DD;i<22#^eKDd8T;UuP48{D-8OE$^|svMcO9Yw zFx@$_Nn_op;tPNS>sqyDCkO$WH~RYdA~;JF?(k;E>Da z#=n6Tf;_|8e^E6(k)b|lozV}kCmoe}lWkf8X)J(FB$FS~@4QI{QM9R(fCyS5(<)JO zBY1BZ(IXs@@gjnjJGQo=Y0R(SdMFPHa_D7eP|$)WLxMDOllq|wdR~Kuy5JY&`r=a2 zgSS|uDFF#SPa0YwOiEpmjDBdNd*T<){#@`|7?+%EhUh$=;ZuDfr5!|zi^Po(2z3;q z`nr8RnJYZ9pf6nw_%M9|o?r<1`N|%@|$KI)~iY3xe8qJKAQk;1vp8 z=P(H$&zQEsosR@K`haU{S)OmW=;lY)LqXlwHD=H8UozF7c4utzcoJi+rK^jkN@$X8@JzjtM3dy^Yk<0u;z-Vo_umV z`|PuR#{j=4X0GR4!<^xBzHL@0+fyZ_<-=fhLQ#}o90YD716;+~0+zH2K`X7wb5{~h zj`ZX(1y`ypn`E`Zga?r3U>&rA#ZF*50c3P=HfiuXY5GZ?iKbwxGqAufq3Jm~Fz3iF z`oHBFr?^B}GwI0$Axj4RWTj65$WUnXR9rj(kjP062w7ye9jiPuc+A_V`l zSWjpErN9|IQ2~g*12v(ogh1+)e8+K0ctI`wn)4hpbbR2axLQp?rhYtM1*9QTum)oC z%2l)4-v;AF-|a2*R1f$dBPJhVl~>%8+D`&i_lkZzlqxKP2KcN%*QISO^i(F(f7I+KcBab{b zy+nliFj1_pv&b0!tDCE@y+#|tLt~r2S;8jI(4uyQvYDzz)IlY(qYx7=z9p;n!F1~9 zd~E4<(NRbkQfHE+jK?=D;Eb8+_}Cqlws{nmp3ujy*zc{J^d7q4kTyYi;gbyTUCyJ& zj*jns_uD4L9>4Wk?A&GKuYdOKI}n?sg#WU%8n+)h=zFUQE3dqA9N)@Dj$XqAe9o@5 zv3LJ|>;K3{KRTX%_8D*BW50ZX-l&#duDpxhf0slaUxkD=cKOh|8Vgi& zi&i$UC1`JZa|d2&zirpPRt8m;sdDlF7m&^X-G-rM0U*7S>pBSf#NYKYok^o>qCCGBy|is180)(eFeDSik+-d1UB- zt;UJIX>Fr1!qFFkw@uh?(;%ux-?7Due>h_3IU3)`HuL}8%uC0&k1J?H%+n$Ia4y`? zSmtqQIBvY@#_{XF{_Eqv{H_0TeCR_T82{$~>Q9YJF1&bb9NQd6jvTR$eS7&|edb+( z>Wj`YHMV!A`>*P2>s1!pgLeCvz7V7*=(bGkYq;_OJeC0{@}|`n56B{qKp}F`M>;^7 zth;6hLwxB_Cgawr-w0OP1c1139z(Qg=T&AKt!Nd%O!l7C?^NkluzdFiK#0~O zRJxT8;98IDGFo}pOL^uXKBSE^nea*&$48maq7MNoGi`93>qKA^rT{c8KB-Kh0??_< zet>;ZXfd6qL!z6H3OsGPTPvfwa!%x>lUH4F)wuYA3kE;=K_fOX(|a7yKf4aFLcux6 z7DbWE@E7!;Q1&kftj{nd7BJh0GqBTbW0Xf!pUoB^^P}{@E#k=pL7xv_D$H&D(!qVPV)q5rkAJAdX4{7S zvV(kA!#wnH%8GU_Zzxm8Baa)v~U~ax#yoxhh~DT6AX7QxqAMiAN|N; zIUvg~INCnpjo&_P5?*)hwURFaF9_N;TPL$wpd^=xOeqGLjEqdmh*KBaYX(;cV)KCX zBYDmgm=G=L6LY^Q!6wZF7C*3vKt#!~?lK^&S(U|JXm}Lb3wH3VG9}}I?>;aNKd;4* zfV%?6PaOB1&I1PyjyGI?z3F}B)p~Gg@gvXvWfRyoqqBl=v74-H@PFijo@ufv=z5_e zo4=V&dYrZ$LMJj z7LwsRXKWtZ7?)pu#dyzq->Z!?wPe#D9euZ=3{aZBrdWPq^As7eh>%BNyA4!#^)D9u zpZ)A-{d590`M1WhkH@6}9)Z64nycK`kp;AEeAvj}ci(5n1K)e7?((8Adhu>d(?NOK zYilEar-EmF*GFZH34V|K3%~e_e&acdkF+VGB&GC1n-=3vd3~T$@EDs`oE%t`$JV9+ zhe6p)DqySf#<@=LC!cXrazz_{z``wqI!st4tV?OIqyrf*rZbUjU|hSr?F~U}RXzs? zj=lroGUP%iqz?&{Ax=l<&F(si9`e$aM_xgvZqy$?n;9O#G$zbLDlzR~l9Fq*X<`>R z&rR^lUR>)YDf#qG()bJmXCD!WDy`Trnt=>^i$3Mxz+k`ph}<9wXkVdShoCJ({8+#- z{mLc5%g8+V!$%hx6#AnpUN!S3!L>*Jxtd8G38B$O@gMAeG^VVy7R<{XqsH$sJe2fbm$d~ zDh_aET~r5*tDMLNeMt9S(@!1&3|0*i?+PQw>&1-}zYC-RrHjRxAT znLr2OjAp$18y`EEq-;{K&BR3mG%aOFO1V<%KY`RU_^xw!iqv-bqC`U%AePtyrpW$l z>hM-*T-)GzLPu;AjthVEYx+O^_?BC48HWxXQeNjK#zbkDOkqs;!^L{eYZ)Jt-6Rx< z%~J)f|6c^Gs%pb`0(g8e6EE8@pqP4e&h=c@HT5Ff^>f;(z+7+my5F!?0h88n#(*ZJ zp&_LhOzQ_)-qO~I9av;KHO0tfo)Tus0+8Q{`;$S{mocPt*69IX+$J%h=!>G)+=^vg z<`^0BSI)u0OqJ2svR{Rr;4@!3+Ny)5eqBKMjDr@hCbz^#P9xF?mamUHB1Nswv?;Gd z;)Y4gEH8_4qyc5qY=8i{l{75NW;s(D+J$_>lAp4rT~X*{eyc@!(3!F=&?)M>3_@=PJZ>?jTjWLzfaCjnRSO zj14V;$p>H}dj9$6$Ab?&=(~~VU{l0}0Dfwid+2Z@MK^-g<~xz{!66v3G6F z|G)dOkAK{Efawd=Y)yFXegf2${==JA-~01FKlZ51kJ(dS1!T5yypeein{=D#66>Yd z_7z}5+Yh?`3h4(w_<=US`>db-&*RXWTDZRH*4xH)uX~*@@W6LUee%SK<4TEJ!g-Ya zu^&A$zH>^QZ3%5OtQo^4Q@@SAVS?z!hZcO39 zB=`=lL=phcJst;&tjQA6pklEbT*Bl6Y%;Qxd5b$3DZYU zOokAu#t8}DHc*~<(J0de4Q+Z1h~Q1tHkC}gmXgpkk4s}fN{YV7m5mRe@db@8FeG2> z1(C~Aah4nH5gi^A2?36Am7-jr!Q?15?-?Q0)%?Bmj_1H*?iV z=T7co^YgP^yIvSK-*khi+@Gnt_=!pMSYm8=Ekl{`y%|~R={lbdXT$%=p;gYRNt{_9 zwuWxCeAVoAbeL8^m2%*&N09L;El9m6W090al?N2ZFq#(L zWbv&MLQkKeNT4r(t_&69Rw!Sm2V-}A)*7m0^xd;9pf z_~Hx4>#x6loRGgz;G4=S%-vY-+`KUMYxB5Yi!Z-S1-nFG9hh787{|#e3Jgg?o4O!6 zOvI9Z4t2#p(4a5;kx7!08NzQ-PJ06f3qF%CtO1`2XV0Cp$5)&G;17P^8%n+&U!G^@;FPx)fbb+5mE-0`M2dsAvwwJrYVr8e~Kwe{VO zKlj;tg^w2hh8tq(^#TGcwm2{jPL1<;>6RAJD1&EX>-c!fo9`GmUjK%%eVn$;-zBjb zXJH)2*{~#KN5-wP)Q`#`U%0e5&~rm)AQGofjyv}xgY+ov!3Z?>pw;ktfq zA#k*t`i||T$|w;2WcOdm^M(o0nx|TCY>Y0_=7)~C50fc_5WMRv8rz^aA_R;z0p$v| zD+msX6nlIJd<~!SNgtWANojvbgN4Q)ib6}R4HipD%Gw@_BX)o%X$mqgC@Jbqt* ziof{fuZ+L?*Z%M0m^Q~;5M>kXO|aykdukKwwnrk9y75ukKrFjmr^?!P=?W$yT|6+_dNjakMs$ZfU|Fe zqEB|4@gx&6x}QRmS_J&`l49~KJxQk%7k!G!?eE$;8-8wbN{3O90o}O zPcQhUM6ErHSJ-}GTj#|+e&ad+ygYg*6dFtu0xxpr<>O@_oht2QyspI1{uemh84b`Gy7r))Ke`A3+ z1^83Cd6Cf`HX+o@K9ZcJZ!9;y_HQ@K4#pLaDmGpGD_Z*zP`$|7Vq_?ZJZx1^l^nZH z^Z}u5pZiT7DFW&G$9>{qSwT6h;pN3l+!1`>fd|afZ;bW=O6&DoZo0*HOX(17imX;g z+Q@f8h2Yd}e6|9w!YN<4IeO&i_}u3|?+rPH{7#mBw|R7P zTyXyRImAzOo&DsvtW4_mc(f9{KBQU;Enl(W8%yJ!{fUJ?^$ z{~SMBwzhB0zGMM%LUp|K;!DQQ{p`<=9rQ^MsOfm~?7Dqx%0 z$jeV&6j8)^20i4nD7UQ?Cc{B_tW+pm7ORq}e$$&Z&*z{gTG~Tpl&h%ur>A#Jn>w^y z<9tY+d3jsfym9nlB_)u^=Pn`eja?$S)F%ByG1Zn`NHBlXwp_PK%?C=lUEmQTCR(Uz zAyfOeX+m`CVjEXz5+@t%PR0M=X5q zgU}&kVuXh{at%dm+e%+aQDChCe&%TVsJGKD>(W(VPNcpz9wGQap*PUj2P-XUzkn2Y ztVp)UuFAVUrYV`Qa>#`y+7+7EhgXj4JbS^R3&wTY1ar~3H_41L^9n4JzTpeK^}_j_d5 z8sb%01!iz3(t&U?s1;9E8UP<$8o&4`QRHD-Whrz~@}^T9M3UB54bGu?1(9naF9&J}&bG7KAzeCjOpffsyhL=gP>FCF{ zYzZg#%0uhAae!|jq7#;_6yk|FS{KlC;PZ z^u33)=-G0*`xk#taQS7IjVrHwtxiJoQv$KA>}zfEL#o_(N=i96C9M-9AW=+&-;F}9 z(Qq}Nz~acy{m$yaSzl<=_XLzF@IQlD?5V9ai^1o|3;D=U>bSPPHXeHDA#Wb{?cZ-a zZ(ikYiml@-85_qo#zhxgFz&kRE|;Y!_OhsR3I&Q;udS)CaTg^gqqHw}5~u#Dhv!Qb zv5EcaSHJ4V(bw0s2$Y??m3nJ)!yAkD{rvmJfdl((f8X6lHf6}^ID(N6&D5-#=>F?N`i@z%I3V37*g$K+_U$~Qm- zKXR>U#s4K2{^GHzPACr!|K}T8@r8881JU!Q^#xgea2qx){T4rzu8N^!+@soRjE{cwBu#rElSO_OsI~>L7;H_FF-IBW{ixW7&WSwP!xK~3Y&D91=XXA&dGPz=ymQYp9%BCsf&3t$P#L$3mq&EO5&=_$ zCpLg`0(B_6CtN}{x}9(6^b!Z`%&!98+}*0r3J`=ST6OF?bsY;2rR}@jCtmXO-Ikp~b^p-$AHHjN+ODyrFhJMAN(q8nDb{ ztP2@kCLr0tP`c*|1xl+D>TAOL0%rRUFgY};J>wW&zKL|$H8!_4$Lp`VZk&HEzXxWX z4Bt#tP_le6sNOXK$*eB@KdA%+fNHyXth&7TJQnmtw$ni-7R)A)>Kx_pRjgp$3dwPl zPQdd-FoB|gcga*x9;GQ4(6%*U%~#}wU-l=rgGGZYJ(d}oCIu#JAtyPAuC(PTY3-8L z7MM2Q6#(D50joa~Omrpd6@YHPKH6SoY&ALD%xUovF`>Iy$bN3 z2L~0jeo0_K!KG%EZ)|La-OQBj9v5DGaV$MF;lk>k}C}9c8>&j0)SbTfrqEbs4% z1|Ychi_s1#pXe01u4Pwr%U+Ai1|a<=V1I!Xe~X}QF!09QUibshS&#umQ_34Er&^B6 zxImJ!kw@k?j*U-z;uF!SI{NW>@gbK*B##r*7xu|7zx4k1%Rl?v=9rJw7D}6Wp#WZj z-HwzACBnXobn6%`v|- zMvW;bbUnmZw$4!Y8L*9zTu6hPHosM$Y7<>;M=q)Q8419qAO&ek>d;0~XQJ_dQR6aQjMs$+TQ}9ha{D$X<_W@I~8gLVG%v z54^>KR;d<8-OkaQj&6fs%XflO!|#|#zDy08r&g_bf75L&vkc>x}68$5ms zA8nmB1AN3r+EI+?vlhj0QSJ*Cq_99MDSz?7uIrTtqd|>2ZQjo&0_-uzE1rYR8git z`?<(v<}`o{zDriP4LkF|nQ&)<$ioQC(1*STvhCuaeA-KKNK@QOaC*K|+jHzPK&A~eu5)+<+{cB%eb zIw#$6#~qPX{@}pym&iJV9>C|I&|gIba~|4d8@9sW5DXGPD52&|E5Uih3w}Y$g7ycr2DjyeB>}J2yczfSr0OME zw$+UxeGrpZY;n=gem=rwpetsyT9zWrGQDV2htPsRN8u(J z#n0f5@fA}#2?D7+{OAy^RjI7_TP`H#RU8`RLRNAhE}7P=*_ooF{LkT$Bh*;=*uveh z1N#pk&cJ|u?6F6EN6d@NpwWgFg;V3otFQK(cDrrT4x&&LH_G0!lg0Ax7-v~cJ57jS z-KIV{%x6Q#9v5O@(&9I^E*BtzNj-0*W-*xs z|7Y&K*MB3ln*|?o#EWn8zqgUiBU$fw`#Z*ES6<;qgprUoP+Y=0=CJD&`pqgj9Te<2 zm!lmYlux9G-}FBC;Dffc>&5S%c+uGHZ+`Q*_PW<;BQBf7pYckJ@3IKuF7Ow=@TKwi zV~>sXdL)v^ck*~4{vwiH(l>3w#77k{1>)nIC;S-nyY9Nn8~<%Bo~;vJ`fqJc_-(vj z#6+Y?5e4D5Hz@NM6Rv4nSDfY~ zi$wUzPJOfbD!@J`eOMX#iM|<=qOo8bCL}%;Zuc(#+&cmjpCZHvTY!4zAs&70jcDtJ ziSof+Ibw~I+z}%gKl;&62mF9U_aw#2^K^sAZL`aiF`cOFgFxmKg1}XfMd)grRU%b6 z+m?E!ly)ZyJ;GP~OQCUOf}77%z}!D95ncuNeE`}L)r&6MFB?)f@l?6_9TgqHy0BL{ zZUJJ8MN_JTirgLw$iWY3gWxQS0H3Rk7s#VGdh)olQ^6_g)1zdhExXSnLu1eLyt2## zLi<0dna4~q(_&fojWTp9F-puVltKF99|dq*r!v?ZWJ%i|TPL>svz+z4dm`O^L%uvI zS?b{Do_C%fe`Z?b#d&}52Y)#J!GH4)$ANPXYTVI3?F8F$e2a4gea~8Lj|~*q1}aG* zlTFMJ#FB)D1rA&EVU*z3onTj=0l$PZ6)$m^h>RZBab^RyR-Fp%CKYW5_c?GCcES>G z7eG&j^PF+CH`!HY+vCoO2Xs__O)4_l&!z*HiIBp?qRj$*hLW^OgFRIbW07aRk{fI| zg`dWUu>zASkBsI~)O>kDApBtBYlRetmcj`tgFT!_MCfvChS3lvf6%LbNSeF4KXd0> zJU91Gv}&LhU96gXhD?F;peFfI2XFze>C8{MWSNPqndKPHeSjcODFY{UK3&|`W zYk4V<(G;SGZ%6``L4tF4bdfig28DHa4$+5sMIZlE($1!p|gER1PQ zPfVX6ra*D(&*=!9C73S7DYFcLFKP(o*^G3sJ_6?9V?Kq6CbCGUOSVMmtF-B0A!?>q z0J;wG2&&PLdQgYfpD4C#ssN*}e9s(Ob^-9=rPKyQqAq_GRv|y_6}SV~dufU|UU_e5 z@S+?q9FBD(OdcigqtbJO0bbmLXQrT0h@2L_WPr=nd!^O;RvMg139-(jLAKG_D!axaz8_ zwHcs-@)vS!Psnmmu)Wg51Oe?0r{K23V${OP;8QTIaJ%@O z6bpHC3R(s}ubBM|Pio?(lfzj~^a;<)Z-Yz~*@OxZ#Ey zM2$Q*l6h94>V%#cp-}cJNt`x9VQh0bHkC{fAx2;93vU(>1l0)^a-N(+?yHWLMFBYF zndqszn;?X~E>qw!<3=ZuEAIG*I{HqL4Z*Jp+u}Px`?C3KSRN2&1#YPOGWXB7DY1A_zolEzTN zbWKjYtAGtKn`kbekoTQvm8W&njyx4X#kwDOGu7#eGoWKD0$fLIZXA(mn_jVt$jcY< zlgSOpS5$eobMv(vmz54>J%<3rn5fIcOZ|Y{wRUj;arozC<}??;t0I!_xuD%CDHFd7 zNYf^wFgoqvGTT7kkWbz3?ajcDeOrWrJ0vzT)djL3atfFDnOYqwUBB*nzYK6U`Z|yfBHqG6@|Td@I_=o(R#D# zOPfLJb_Ykg`18S5go@4np^z9tq4+5Pz?g$S?u%`^ zdR~E+x&4K)fB)X`t#5sEeDDJw)S`FK*t^bOBE|21zkucv+mB2uj~^Hnk%L0X!YG3+ zaNz&e{hMCr>5Ow3Mw22vu`a;4GvJqSrs5?I(~vX!(_VAl;+gNN9%lkd?aK;Fu#5<` zEPJ;6Pa{P>W$~9&irt=+);Zds_OnGHP$oXH-v!=)5vvStHaY!dms#2f4y79iHT)(@ zj)@*DV8rzTOMK*m!AwIJs?Pwe?yqGz-ocXhJgJr(Iv(zzobe& zFGGXhsaIhB223DZD9T7OKQ~+2T=HC5mBX))K0~S6IfTad-T@*0z>eIUh)iP{ZYPLK zCt0M5h8S^KJ7^4=01U{;XkISBlWLr)rgEZ`8%3%s2EJ%W(^sed8f?mnU5N3g^nD9su^|?6j#N z1UOt--&v_ibLu>BsIUhk3#GYPiq?4raaSQh%RUJ;%|Uoe$b$tP8_yFgNqSP8WDu3GXIAE7KsNw1Ds5F zaaF&>ip{{|k3T-1edZaJNtR9uR$B~AzSmrR^*DH7zvxR3fNCdDgnz26_=udeP15Db zBv`lkOsZJhF6wO2IyeTPs5bYR2$XOwm{`6`J(4!E>S*hb(^-ek_=%Bi}@3J8^>IE-2 zuekEHV~yYMsqCowFMrGRj(5BxdkDgyShgugbZIfHm}OQhED1 zG5(~6Dpeji-soR<{kZ-OZ&01JVO9|~`6&pA^oHM(v2`tWA|HNt0qmOl0#R5vU{9TJ z&2@>SZ_rMzfs_7ij* zfAOK>sGBadSWf7=FA#&ZlWYTg#!QQYT*wiQB5+9v16|21S}4I;s>P(N`DYvv2a-sd zzvZURYzmSJgncp2L}z=cr}#;OZ+`F-t=pk!r6{xw%Qk}+-s-O;@=cji^CM`0 zQbva&dIG8C!iKJmXpOV)E2!M(8S6_PeC#C$Z{e}E^%<9W7hTE52a|8WGroo61M#x& zx)tGrmKYlGcKcceHY#LZfu^?l79m6}V*4UN=%L~-($<9+t!%)j`~!j|i`V8U&125b zJpJ_e>%aM%kn2ST4SNqP-Mp7RtkltQ@;AXcOU?M6OhrtvOu z+wOsZY^XSrx5-@x;j*z$CBZq5v#%8NU;>J&vs? zJPSKqX7s6XM1Ax6*S}$0aN$L&>#4DC@7`%Xh##1tTfcBV#{}9ZfJvQS;EHzXhn-+P zc#<%f(kRww!7p`jI#a2>!Z9~Oqabg%7zjP($)n$M2x({wpT01IMJa}#c+&3!JrNMD zJGJGuuy_hRKA#sla|rWH^Op{N?A_)E&}TVePf7Pxf#TA9Mp%)x;M>X5_*ME>09vk- zsvq;H(w?7{PxV%P+vCEVO3tGzw18=5w33U=t1yAQY!3?BLEQjg)B($(OPD)@8BJ?` z@WK(%Sh+(+BSJufE@({;jV2Fpkh*(UhGU3LZAi9gdmtc30bCDQ!yrRhg1U4r>!E9tL|h9J_p?w`i!fLG}x= zcJrHwYzlfnK##7=F1=)&@PDU@N0sp45T5$jGV=bUJo+h%H7*y5Inm7%Y;jNrax<;t zs<+$5$xKYvsl4&#^Fg+<(GL&2_K}E9i%iA4rOS_2)<6ebrkMYOeD=9#{lCC_v?=yU z)g{Ot~BO7BvC;SI;1`~2s;+2l94e&Zxpebx4P-2i<`Y6R*xy{K?K734oZ?uk#4EmvVnHls@02cg9eW#zAFqOd**=aY0xu}44!86E)j)trvA@Dk^ z8Ba=}2a)J>)*16~Cycvz;9V1=^MS1|g4QIKkLXz}bAg`z%OW{+l_VP`r*`2ZgHp-&g zlE=?McnauufA@FCx4-?Jap=(bDnU-Dm=Af$BYg-PTsbom*BCH;{NwZlWs^%fy@bl! zp-`L-XTkw5hju5(@}iYaI|!?*Q47lK^5YpK3-57>FaTQl$im4g@BTqsC{L2G0w@t- z`cZ;6Iw%!%-}IWr0-X)CFwl@G(M1j2KbK=5puF3Uq;$Gm{Pa6gU0?7WgafybEfNciU9BFjcE=a^}IC3J>(Xq7T)r@e2ObO@kRg!$bwAPp|O4UzC7 zAVx$ZeW~K71+BtgsQ-gda;oag*SVTKlQ|T>glJaMShuNU=wip;Db}$R2lncvWuW2k>GUELY$PHuM{C|U^hw*kHA}n z81rJW-G1xwcfb4H@wKmh&A&H_iEK7`fedL&AIG;g#|<~$IBt34ZG->iOncI1vd)`V zWXG@k2G|7%QwTooa7q>N!ijcrLiMBXroj~i&?$T2MHh~nZ@p!_@zz__HtX)o?)C+Y z^R45XlC6#F-u3a&_Z}Qy{_>anHfap;=}~pz0fKGO@Zruc7dx;=`}nbS;<)kHh6Ni( zH^v=rzGGZ<^=tE6Uzy0burE!=g##!Bi~%AJ;s=Ow;i&r+g{fD3CV;5Zj+HNd1GWh7 zN8B5a+$BHJf-iSg6c%FB=aB&hS{E5_VC=wRS_-9?xl=->O=$t`Mhp zNVG4C*bd1r;Ol;u z`q3j)UaF$YjG8D@x0yC_u**Djsi0d;2ny_h)-QgN-QMOena(*m(;CRy2hm5Gdg3$J z*RtSE9b8_t9yHvky&NtRku;(`SCHocUIG&%ra$kI@emq|;oN zVkxbZ^`xI-58yi0UjxoSd8J@AJ2c`|)Z@gn)ube{CLak8mGfRJh1PzssLF>l=M6!# z1EwjAYL0raKKF3}=f)duFz+^WE)2DLeN6U&SlDUa5D-^-!j&GtxCxK@+FylpB>&p4 zt|bWJTj2tlWk-x(+gCZ4NsjoP^mw99knqV zGW-&j$TV1p0HU%#ZI+_Yfsc;~R;7TAj;hR)jq?crXwqKZ6m;3YQc!gP($=^{{*&Df z)I)gB@fD!Tm=3|zpH&742R?~kg%<mVA7l_lh0oJWR$h46G05Y-~##On@HNOuvD%yjTCA^2(I z3Xj+=0#e0(Bv=zoaN#FibAzBJSNQ3roS;iCCkD#X{UV!3XtsHIkus@I9{*)CfI`Ob z_a6Fwlu#-f^J@gN0j8m@yY4z~mfOd+OJ6u_f>WR*jD?%BPzEZc8J|=SnwI4l+a~+U z6hgOU;emM~gO56juuphqtdoJj15+}*i0nm+g4@#N$chcz6@2=sr^X-u@gMsyfskd{ z(zB)w*loAHNj}S8{J5PPtg`@TxU9=5qd!Xzq6*)ACL0dgk(>^7qD3b`%Lc zffgp{;OEqgENrg2DL~q~IPP8J@u~C<3hAaBn;YZa&)jR-{DsoV6KZqhs1TPy%?rVJ zYwBHh^LI$v0Q)3_Zc$2~t#aKQ`R$rsGJAV%Mvn{V5zTA3Jd(FQsC` zo4QPtZpZaC9#h^kjvhHS)x%z~Sfv%K8ynbkqmKmzGWly1-yv3>cI8QjLx;{AKl`&k zn~lDB*o5&IxPMbDgS%!1mD$_+rtc=We_?CmCKeLu=RJ?%XZJ&qMMnCs{VG2#-pJ)Z}MokdfO4nFg(paM8BHH{koQ{zXMv&?Rs1Ff!XuFoc zfxqS%#r-*F$W!amlvU+ z#lU1a)rTnd&yCP!-js*5xuUGFN{X+F%wu^%VJzz4Bc4KNCQuqQka=hhfaMFiKLHk9 z@@%7$lgK4qN$%JY`iXSN$P(`oub9g~pg3=G&N}zp1LOKPyndYEoF#jFQvyangt4G> z*pT?orf_fqNW4-PA2h-WH~VJNUhUkaqMN%|-sxbFCLLbf{$pv>m7DdD=bzjBDIx$R$tov_P;!O#v;UQWwoBOIP~ zG&^u^40l;O*_Y@A>C7n!0zM6DCSuD?gP6vA3tBRU(7D{OXg;A@2C|oS1;8s>@|%_f zIHHzYP_!(xIYC1g5zxVFW`Xh~I}1JnlO=H3NfUy9b3z%iHF5HIZ|sILJWQs(!?J7l zc;=aB#*#rW?u!*^Kd$F`(^jeKRPZicLVz^Y3?rvsxn;{Kj!mFrJuW5ohHnpk0J7 zKLE}P&-BisIwkSHeTf{!uqGMMjk`>E~YDpl$ZA7qbFiBou(1 z0C@$bFS*f2GBS*})FQw(P+*_~RTxLs+4)IIz_Juo+zIO^tiYLZ&`x*U#XnP!!e6Lq z-U>V9w0~@!8Inir3MF(CFSeE+LECiBL&7=Tw9Z5}Az7(`t}=quSqY&$C&-4_1qdnH zMHdsKuITkbRv(E!N^FJ{x#iX*9-D9?EXj`ispqy+_E=@2#ZP{}rQoI2&4Un{tRS#r$DPXY{ z4z@~^&A5+uJD|+yDG#dT5~ehLH!%!d*5#I6U|h*;Fny8%+mTOGE@c>$b=8fJPiKhk zt<6op5bN4&UpG!{=SeI+)`uAux!?m?a!%8CCTLn8m7V6L;*Wt5J5dQ-=7h5=V3e%1 ztpz0(nAZ#d1xTLd%wki|Gx;qt3SV`w6r&c(1WVjf($cV1dFMQsq>T&8u-bM3 zFspMyU|FBjx&B3gG*5PZb}h9W;r(v&x?byw1#0vcF)zx-d1W6yZ z8Alp~lLGN~nehEsQ;`~138Uckbv)=`RH7GEi9`j$Y}H~_9wTxkHTK}s^ck|qqt4Gi ze|Y@hhd&r=dw6Uvzb)>K-s@j~opA_&mbX&2c)a0{eTD&TyFjwhMZ1|^McL>qXd2?s z8SFrduwH;8RA~bM8Wwx?$emZdqC#Kmg@pPl9Ue%|8GHBa9gjWw*!cQ4zCQNtUspZz zxGDi)!3X`;=Ek`B=9>q6hP}p}fC~@U$Z+q?9QwIq!{glF{myrso}MH@uRj3V1m&BxU27g6 z$Z*e+-*_?D)vvvJ+;r1Tz7T@XY_4qZ0-1KRGZCS_E`BbScuXz;eJlPDP$jq7Dtd;J zfh^PY0%Qdm2kkEEIt z-vWq{TXcEaA~Ia;-^UlNAo%7FK6Ag5hN%uFiF`6dId?6HDdyuRjAn@Msh2$0avZy* zNJI=WCAf9M1Fii5-nh*Bysed77H66xl#ky+g$TyziQ`zqDKs(mE>wsNj`$*N zIsLSvN`De)&deW4FL90)mKtWQ)J^uNu!DUG!9;}Zi}SR==Lg}fv+>Zk0ZMzkBd>7_ zFkS*(h5(w!7x)0>t8cgcE^%@}Bd}#kBF0To-4D6eA2LH^2%(URy}`x)ZY|0~*Rof} z&78Ck8lVNt>Xc#&4}OXTtfOql4rqN2O|LZb(Z?IH0!U{51Pwb)I#A}mAZU^mn+TJhf3bjW*E!j&zY2`)`nnPzHQx%KDL6hcbFEpNcLLP1jb4SF zP~MRfS$xy!gvurYEN)&l4UX<~9PP)*s+{9YD=;EFkkO2ucWS`a?3DC0>p+mspB|~O zSd3=SAc^v#bAt<0Co~n9&47*6(j5Ujd=yf*$elWja7jUjFN#*IS!~D`pzJ4;#GZ!I zVVqZ&k|^1mCpP0J)x&p+6nGSxySuy)h=u=Sk3E(bEvQ#h4=mx)VALKsxPM%I&9&nM ze^-Ohm}H=>rVWRTi+^pT>-7S^xe*SD=r0Q`hZBFAAa%uJ7RGKL>Oe>}3daUKXfWOg zTW9=Yn96qNw-{1Lgdf;Qt*x&~2KvM!WBDK4bNF9EmGfKRAN}Z2ZS;}D-`?a(EB^s| z_3K_Y&O7e{ZH%~+jC|Droz#(Ftz=UMn8t0AKAb#6p_@R-c&7Mmad^WYd1ki1d-IJ? zg64l>xPW3$%IDjDj8}b3M!M_Ju6C<5$%&}PZyQ@%$7+;!L8Di1FdD5w9}9?{u$^Qc^bg=f>jvweIkcjCza&??X_r%s+w)x=~D@vuRz zzBnzC1e;sO{lYBwIZ)!~2_l z%y%Sps0}1`_<|3#mJ40vT9-562-E}m*+<~5GHk-9zqmT0Wh{g?^!fj0rG=Yhpa(wC z?m(hb%!L-b0p9Fg2P8CY%Vra3d_oq__(cH{wGU&|7xrlH!U3kGjZ3$|I3%FM;sfR( zgY4)afm|6B6N9Qlbh&O;3LrD}wQs8(z!%E`3U9%4n;{(Bgr~14a+4!PavhtpY?a!K zQ;^`4AZ+3qn|`ZA7A z2V73AGgd+9I1y6kRejSrxbgrLX|J$*OyrNlBW`*@5=5#O^H00lgBtIv=9KH4L>;^V z6M*lr=EzKm0IEx$pXNC5opurlpzG844(bEhG)3RC+_4hDEI`PVr(NA`1#WwM1CROi zp-eI@ed2@G1S{aDDX5I(obq|+g~7jhyyrddjV4VjTsUTy^(13ZN!8JO>UZ?Q06GY< zE12%1idjSShl_)v$v7wvVt^pGPgn*n?fc392qWRz0ybb%efg$VyrANDe+C(wDq$ zP`=j=4b8U`+Lr(+H}?XXZ3VsHc_jebkk~651DCw6=!= zbP@+F*OMd}1?V*JyTMoR&@y1F$OD0pQ5_!2z!{>K*bF&X4j(#VY7rh{%ABr~ylHD; zZrwWB^Pj$)(6IwNE?DC(FpG%Y=ZuFQdeFa%DrA#@UWOATRSwKfdVucuBAW86~ zot_??K56GdDBWCHtdYZy(bcw6_e#Q|zyhKB8R(=f!?fh7>pA1Z_6fByf9VvPImvNB z;E%rXjqxzQe_qofpcV6Fh_q)b<=bfi>78^lCLlqs#qZ1?OJJuj1 z{?f;`scy1&kNgaW`>gfh$2qTqecn~|Nrism{I0QY-+uo#+b1)9sVgsd`@;SAk7unU)ZBx}NB zBl0OzOnJOcc?z(Ffd7lMAbp`1=Rn#{VEG6PuhHmoA^0NE!M2#dM8U~7E*Fm2X~*%6 zLHSyD$~Ra}`xjm`u$WeX53;5^7!>NzvfU)|b<*&L-V1_>K5goxY1|whAMnvsE+r#g zj>JH^Zp#gAn4Gg*<`WiAZ973;@Kj>JNaQN=MHYWR2`4h>gKvnO_^YvIP6Xb3_#u78 zq~-#;4;C$$ij9`8v>gc2ZBO$Dkl%a&Joc0L!`zU1%o|l8G-(sz;Kc!o?HlRB_K=3g zx*Vbl36=*falxda6P6>2FbI&Xqh-W4NL`G6&NU=CfNVjEJO|+umnu{QoqeWnW*BX1 zd2_Su-OwEFx?pFNLt12^(1ggAY~P-HnzW$t;QHc3!e zo(Q}lgdU*4JQRr!0hi5Gk2xQOfZYeD zt9^|`mkX!1qeh^C#sM^Ci9IWD4n!99=A9VW!Bc3LUw-+x_L^(`Voubu*4x-PDq2am zOl)ZRrGL^zzHvH8K>UTJoWE0qgk`(74^mGj6z~=4=D_PsTVt+dOt9n^-u{ulLrZa$ zix2&=Y=@qjUu-*kP7@W6f!|^eFEXYgFrV)6^W+c3(aAS@r+Nuko`cW%1fa~6OvnZ` zMR}=w6v9{G3_vfIgW@bhH;6w@$eHa$g>ERYG{VFiQ4Kk{rVKgy-O`?Nn@ohrvf)1IT(1ka+U}FW)dCpp(!9f(hG@P~#C@b`c4$KxA+^haLAQa@f4(s%K_m@U5< z+D66wLJ{aTH#Yoq#M|HT4)NkxbkepEo2U}NLY~ug(rb5SDJLp$M{)*u-|qsvl?Kdt3V%qA{=(>ke-3h6tc)Y0|BbdHcwbfw2QV~V!?)wB~ma`9LB(X^&>almD({1YtG))=}3 z{6M=a36!qTg)c>It5QP54{kw)q>0cSsJL{moYPFN1mjmYFXC5h6yE&8VGCc`<;{(0 zO{CbKw2awT!uatVM1rGkI)`W+O&1t+{^P}Xyd9qT&*v76J?KvyKd!JPBKbwQeS7zf zhaY};{PqVw=sIv-<2(ph7Xp#10Kezhs4;k~V>1Y10KUcpKMW-$K&Jk*h+a*rq6&Nj-JfLExC$ORtQ1_udYQiLK+~4X=NFy~`zQF`jbbJl1{PI*ZpDVRpI$P})l$ zdHdNUMWcAKQYhOdxxLPXC!|U{8(g5`icH5GRN(Uwg~B5f+0LND6a~{fK}f{Hh*GC4x&oQXQ@fEEChd{FR&uM`1G z+B3k!V>=eGGyf+9q#=@EldzYA^`!1Gn}X^OWPQZODh@JOGm$Rjt8f}H_Uugi+L<_* z?wKi2C$7nVBtq*P$y0PNi;2fgOei@dIa%_kgjq9L_^|_m2MBD=n8tJ+s%5c8!^qSg zOx?P|dQgzHGST`R?1jJx$Yk-_KW72W-$YI|F#t#s~&jd^UiYu=iC%5Hm zuE_YVX8j{r;A1(1f;ZHtr~@xioE_8tDxZvmAi zxJ%@&E&Y?a_T)()*rm-TCw#Y?_;~#2bNAir&7c1g3AyO@qr#~Vzn44r;Gyx(ciyeE z`W83-v`-w*(+2L>w!#J|2t3wE%XVngk-dp91NG2?RXU&5Cj28G{mA$q{)hkX z`1ZHHJ=WIty1lu<&EwtBQ8)bP3Q8EgKqSHGjc0gv{D&*L($Ua(CXujwrz;6w%@cI9R=rlQ6!yiM}18S z$QJisG!wqw)_i?@OXFB{Tx8>78yEg~U%-|@_NhsNViJU$MbyWda# zaDKyv$n84DZfpQEp#fz)9l!iDe|B_Jla+hVT?=m#letcH$$`u}I| z&th-Q()&E@t23Wdb5(Z@T|E!%c_b+ghD=ck?Bs$@e3J-C9NCr~K(T?qa&D6#FdRX! zVv&@b0F;y%qMR7f9Fe||W5^6Ck`md?o`>qL=FrXVuBmITI&i>EbUx0YbPN+ZhIFV9_9s)?DNL*^Jn|l zfbV(FdwiD*?`FY1L7oDfr?4d|G*v^m-2n1Fm-v=2^k{Ol(>qL=lo zW0$oBKI&NJ7ziWuBfNT}U;2$t5C$wRJUY;|7>GxTtx=xJAEq;&neFW(f{ttGQwh$I&a2(07<6nk9{BLx?|yfC`Q=wUh%z4Ni^GpR{76zx zf^TqQl#^oP-M%}MSo;=Y>}UhaCqYsmDg#74pXlkBUH0JvUq<^M{xqVz5W)|myl7eg zjtdx^%yACOa?b^e(N_**sjZaHoj$jH-8HxsJ%I>#>p8C5iyIceqsjj@Q#&Fjns`j@z`v7XpR&#(WJf3iLC^i%1F zv$F#XofHoGaU9V{(gF^qp~HFQ%H{38d+yzS_y>R31Lyimy!nz7OH%lii7#`f-3@jG z=22)H+4I&HxRJ`$v*ocXrL9Kfy_@uFR||2SiizPBhQAbzt z_06shonaw$`q5!xrz4w>c1I!ltj_qzTEyS>T~C}@i#R!epC@>D&jDo*%$S#1FW6`P z)xY-t*#7aa{_1w;r8~B>r_W~XONx%hfVsar@0Q4|1H|QtJ`bP#`MO5IK{dFwKU#VO z`Jf-+0=;8rDT(zmx+og^1t72iZt=ekC|H2&(4J~IP!GU9P5<4u#cLAtDWVRKXgZc{ zKb{0>*|fisGeLu3|AOD*NTIvV%J6MfuoFjGYul?f5nID%aJ@jAax#B^ zJ$USUJeRzhM5?1cIwRr(#~B@;#v?3^d}XtV9V9)gR@Fy z1WT8*IiwT1hT#tZ%Cgg1m4AtVPb=vy`uja;3!Y?PdVy*2q(1xd?sqE2g=WX)9?3W0 z7*2H%%t2>h4UR$w;sIya>4U)&7tJiL9zyF=@MvtB+XR)eBoB*HC$?x0V_O_f1 z(Y}157uDVo#GmjP``~&I2~?Mi7RdVXh?DxX%RUR6x+;{!SRgjwr~~C!=UUvvVQcWi zJ6^d3v{mKFMt5|StL>p*zW4a!IY8pKrd@Q6ZSZf+39xsEf%uOMlE|M;eAqE9Tj2LJ zHc>;FYTFHfY?~Ke3>zSM{Tx4{Z!(F!U_m)35865>=vN*w#$O)gb|(TM$+%=3P=ERI z%N_($c4x<^iak!?IFN*w{(tLRAK5`M!tg=yWX^-DjrmNFNZU^&EaC`r_dr?%oq zY8}9b)Mgy4g9aQ}KAFTLFR?WB)Rz8^4xsS?IXHM%XHb_nAg;WnE`KLBi%+P&*~M!WsXXYFr-*j-P(szw)>WjE`A?xxNg`#I6& zKxeG5HgWNeJHG2L&b(+Fne!LUZ~yQg{%ac5{W*|*6&d!IysLnVH!`x-d^S2; zAAz+Gw|^Flukt6!d5i)^{+MuL3<@BcjFzm6X=e^Bz6CJ0|Bt!rbA8uE=s`8!!DX%i z<%5&<=~+q|7c9x6aCM7gGkrWdmo5OC<*jcEsQ02wKjKm+`uvaU3XF3aayI75Ay0cM zxyy6BKz-Ku2p`24nf6`hrW(el#g9nvslr3OHV4=jag4KY$inOX_lOad0Z_-{OBvgq zEH9`bb>zF^1RrJe^DhOYd+xbsd*6HC>r)Pl7+T@Q;w}z|?OA<7Vf7rGNnw1k4Z`s5 zfKal`CE{yb_26njvZXGW#TmK?Z zKkC~_crE6i2bk8~R@GoT^l93Z;%c8jzI;w@8&)}=k`L`_Ry}XPYa#oe9;h4aAof5H zv3FUnL97v{eUy!ANbBTxC4~7<=1$0`f9o^bi!VO!7_i;>aNx*YWFL)AyLkNj z6QB5$2bs1rvOTe`Z4!?WayLBI{GZ;wTr2g&ln-8E+Zul4%faarPdu^x)@MK4amVdz z{7e~NuHWE zf6K!UZts8p57^H^qs9%9;ebPwdco6{)(^It?dyf(V%iMAH$W^3!O4ppy!hJ#E!f-l zp-nU7)j14_sE4YlPfR&|f=XslX3Ms_H7eF&Tn87>97$8(0l69yUw^CDp&^TsijC`S zgTyjHBNaJ$5s7;mns3ddWdZ+#pc5BRAG`Cya#;=q&jRr-}D8w`jv#Zd(w%Do&bxmD5YZBvOL9~y(VVJz-j-_KL z&Gr^yUY{p^t6st!8+p7 zR!1Y4w)7Y%Mb^T-0V@Yac6?A5E-m(3aRB%rR{I?zN$v;5R2OTx^=yiVk7LP>`=wW^ zx(=zT2M_O1c1`JE`5k6`%6xBGYH^Nz1%9kBZt;+eSJGjpKn2unz{e;I)zi zb>?3jj+A3>yl{)PwtKZv4C9(1YFCDIrpeQ6?a}sW?QP-~^XlG=0khdokJA}?>M5Uw069?Mm0YxD8IygBP z$b#qv_V^PzcLz_?*2D!}+$}zv6N{VIUfsU^t#7Mu<8dV)S>P+9CpWx_&~``n&BTH- z&SQ%MjXfUV@yi1q>iPP(U3`E-9690u?*$56CU1MdcY|%}*n|oEkh48Gp;FKoy2_|b zQu}Pi(}M8A$0ObLy{QZE>6}Ep``zzNnX9f>wkz53@LQaByz?D#1zWTwHjt?{jja>H zpm)%%m8Tu{OGyP~(AR@QK?N%nN}7Xl%DW!ok1V{Dv*qz87MzsTATqQd_%uGJw$nLD zed5Wdx6gm>3%w9QA0#oHc$|>8r{W%eoAjRdymx!oyWZvF!Nv-`jPd9@e#5hVMh8Q= z>m)l~d=4)(AB6&tRm=97&;HhS_4?I}&0sSy*?DHo@Pld({%24d0 zN*~ak@SjV6ef4W!-G29XzqQ?S_dVMM9@h_@J4@Q2?K&11-w8nvh88Wki^Xl*kNnt= z=S2EK4lby}3>DIC+wFJWZXI;7cv_k}aXzy{+)u1p6|`kNIYoKVGv(oJAFT*g23Zfz zfvKMaxWUmTLUq(`^62ckgkRNMnbDOLN>FLHIz~RcDeX8rmug`3tp~gTRxDWD5MRck zAJn8zprIZ=$XgNbm>s_uH$AZHypZm^8@)0m-r+BANoI_blss_=FOT2jKvh>)6%@kZ z*6|<)#^TU{{k|c7@aTmR+vBe?!wbfoIPb9dj@ls4sHF{L;wD}T7hdqgn5_1ZCslX- zS{FVG$O#MHu*>#w!6 zOg-@=YfLfIwle06urmmyY{zZN$BN;dgx!1%dlZrLH-D#CScC{=&EVqP^UprJ{kcE) z=eAc~erdb?_B-NF1jEmPGmleyu@4^s1J@k?@YOgjzrrVevCB-Zx%tbntb22(TbjH& z+Am2R=*E%gw2?GAvn;r(r@r!H7$ z>H4;K$lKm^oFm2ZvIU}ZdLjWLfbGhF({KE$6b#8q^Eh)p3-8aKT=UV>ewAYdx}t^A zt1ZXGK@WCe8;m?l3+ACC4}viD z_+jk}kfDv!N|7S$_5FBrF$dNSH0La==_BU4tCf5Q-Z$U?Jq9A}&|op)=zxZe&LOZI z1ZAK{XzvuboSdByyZ{UIxeG&rTl96*1di85fTztq!UI%M=$+?SnBa7V{$f)LS-}j$+Dr;UU zX)6bn7cZXQ&YnNJJ@>*3{Yx3+6dL<%L&zd?W4ry1+qe68A=b_7m1St7TZ{F5**7+{ zc`c&gEheYEA`9x7j}YG3C8D%)qu1Pcfn+j8inyfI6NqZAuJ)N%tdySvO1Hr!!(UDc z`r%;gX4FUT^_$y+4?eJc{No?r-tv~WY!5&D@b)8rhq@hq~T;DQl?IM$-EZIdenw&IzDo+;EuMkaLAht2TeRAMSR?G1h?+UF5pq= zFMRRy{*4GPm7*_va(6;TdwAj1J$K#hUn1G&j2WiMy1UG8rCxgJ2_y$bs(ja zsd{K1g3N;8wNqn=_{gXI4b(0H_rQUja?t}zH*hp&24@=whb>hp-1sW(+7cX<_y#}Y zv*QLx9zhOGkQY1l)vf%L(Ftm7Qdx&I#W8}olP0yi$r%%TfE63p!HVoaq&c9e5V1i= z^{b36GQ=CRSmxK`cR>v0*Cgxe(tv5l_XTY`Kqt{&^AB|$*3n)2#hu;@`5tv)@Z1X z3W=!?WbHF`KueCbe(0~x|L!*c@!iY73H`E!n5#;))<3F9^J{ukG<~~oWL)jvJj!i2Cl4izmPJdRn2%|Y=EoE z1Mlj8=<)#e1CXsK^3v*m@?mZN1Xr{m4nEgh`k;9G3tOPaxsFAut?SDaTaG;AE_`b& ztP5&v7b`X7d>2BXrSMtxhQR?=drHl?P8@kB$tOSYiT%AF0LN};vrl!U;Asc| zk))o0j4wLRzLZLE%v~Z*pmYD=DtwI@$U~onkK9^d@W-%@%K`YP?ecEL z%r>~?$nbRgFAlf5vg*tBvE~Er04L*d?tELBgi^6TFT7r1*`Jm3w*A7 z)OS<#eU1-K^$F59;Pt_ufb2lUSQ9)#*bZ6H2}NlIKLdNm1!OJ1lO_ZY5M&5nwmr!V zPqHpt$TLBr^LW6cmjWFPKO}IdQy{IN}-?HVSEEE?b<*kL(T zWRuq7;7;8~#QGam)UptIQXvlu+o|oYJMZ-5;hATj*{?rU@c z;7I70u^^kfj-a!1hz;JX&Huyx@DKly?MHs(N49(Kx!1>zJj@HD`WaFVtKbp}PtqcL zFxP@6*i0Q*zS-vrP+z#>PXfr$$?_TT_QAkGC%*6~@eLpC=C6$0Q5th}^bYuMfAg{J zOJDrrcKfAE)roL6JXXlTB3JT||M*8gzTJ1<{XQO?F!e+<;CQpW%uDVTjbBOpHVL{h zNx~-*4B#1;FFgPJ_Upg)>)zpAFT&u(8T{Vq6QB6_cK`kN`FK7rw_!(D<<*HV*yeZY zpa1OVwkIEd!oNqlas66Ogs<8b561lcxg!rHj1p4F-&UKn~$ND5CNo3)f`tn1{ z&RYe`W2HhGT5D4M`^+`<@J$;w+kUd#gzi!uGo8t6%O$du7>$HfcV z-~GFPZ~KK`_=WABd+v^W59Dp4!RW~}#eMipZj6&_g9L7kr;$A_!%V4uT2d)~*oI*P zz#ghDKuOqHF{r)5>y?dAeFGv-$+jJ{|8roM4^+OX`wnpVtbSPx3*bGmu3-DPJ|ef4 zqNAn2=vx^5;mXwD(YBj3$HpXT$yq~MZ(f)j{B&%$N?8(!+b$E>`;r{|!58z@z9lDn zdK(t`z%iaeSawIJ)+CK8}j~tFkBH^)-;}QAew%3UB8QmxF zaDpoj&|@S-*U>5*`EpeecH(l2zy#cQQSCqy$8-uhaoygD( zv*m?@ZO3{#6xOO?r?dpL3q4H3dFP*$Ti-(=V zVTVvWyuy+P^l#~$#bMV!^6p3jq3sJkDQre73&5!}*eD+-87vfc=7jfcZ-1MQM00R( z=UsPh_uPArCpwQm@x3e@2zQ_&xMIrZ!3Q4lpwhcwUbSr;VBv%j8lhZmG7B#n_5*I{ z;1c^o%tD)Z!2sSx4SS@cT}xV#q!As2{Y0 z11WYm*RIX)V-q)Ce$|Dzdec zab_pj6C)1#IH}}+ch5?XW(64!{1%uKU@nR<7PtjWZaI3%uV-95_|QY!$3OXr?b;Ro zj6ZaYWqf&(&0X>Af-muQaaH#u7Q5__3-k>+I`O}L^7iRp|Mg$@Z>9K)hoA-ihUuN} zde`>RoQx8GUYdo>u1<)KoT&2`C(nNW``c$e^J#zA$BS(6+eh5PWnU!iqST{k#d;-T z#&4y3*ryo{aeJeNzsdFI!*!8Qgx`AaMe}Nucv@SZi_9`a8-B3 zGnVolj-6-Sr3KOWfQ7ex!ACyqjQpXkcz@tsepLl}lcj#s115O8u2W*17NR-*w-2K5 zGj8QtxU_-NV5fiTg6#)8IFaSrQNW6gbJ)^~SL(zuJ`~^B=mUO@vGP(c&hdlg;M2k+ z&>fRiJNZCkL#Z(^97qL;?bSb`0eFzHJlMnx8~P#+o$WI(XzaoOlF{4lO9(r+Wd_te z^5`ABOKkAWRZ&UcN^ODlrT&Q&j*8{C&j}&@b6eJfzL}p3aQwW2xk@|e4aOLcMt}8d zk8VHz^Z(U$-@W&#k9|Bpd!VVypZ+gAjly@hQli~qvTuzGRWvt8S=*H&GP;j#5J_oI z`!JsaBTR?=7=W&P>0{8#{-Uq#p>|vbu$r2>(G?$uwBrM-4JRNp@bJj1_q0(*>|b$K z!vWt>qFyyexTzmxD3BWC#u*xREy@SpeUa8nlN?b>wh4ch?)gX^MQnTbR)+F}V~m1M zWsePGNZlnZJcir9LBKy~==MKpd`Knbsq4eSBN0e@=$&2nz^*4BRtTR-Te!g^<4T-) z%thWu-tx$H*PVBJ60ACG7%%isiY!2@*&lmhNK9~{I}YI)U(>_M;-ht7MYMqL;KakD z4M~9`Jf4QI_b<3vUv*PHXyYUEc$Y7pvZ^VAqt61$+wat?n_utYbA1Xg?=jiAVOjgg z#Ln>p#@j_$kO z{qF4@?|P^Icgr0){u}t2XTI;wA05#WH*1rVqfn`U>=e)RALZC^wa0zT8{G=a9_HIEcx zv#oLjXPlkh9{a{)+n2ub6(7ZST%mOO@Dm^Vn7>o!Q7??Lpx%r>v=1BT_hdWxfBKuh zvAyu}3)^iu@g*MD^#!q7Q~=+m&+wT?9>IH{9bmqm$yoYhfAo)Tm-vlUbf6!eYdI;0 z>(m+gc-!Ah-4rkuI7-XX0 zLlN}pC76!qp7fLp@NY6G2G@fK${LR3=!-JUy9SBE9=x?v-%^k#S@66YzymfuFwxX7 z&}P`%&gS@_E%jlgK6Onlk2-`XLdH2x+b|kBzR8bo@S%gkl0#9XXYrP#6lk{SZMy)* zNii~j`~YpeE_%xHks|hu?8WJR|{nvitD%yJDU+B9L(12 zyrgt4Qig8pP$F*iLjhff#AD;V5O;)2;zQm?@r(D=C%mjj`^ZCgOL`;37C83>9A{Wg zPQan1xX*Rnj1EYpTpv&%iEVmwrL zeX#_Kpf4F9szKS#yZGGh_%Tp`KQ=ll>Ct|K;5%3S)(3DjnfV|SdHr*)I#|*NX63;r zear@PIzu@)_D|4>IZxwtDBtE^H{N~s-Ts`3vF;sUc!*cDwh1UIbbjJv+OqU7vd$#g zKLL0p#u!1SjY47&K6M18-`E;D<%3e9MS1qcu}6Dh6%T9h?6;V^_P=8#So9`g$73RG zR=2rwp{YYH!y8*vfn^K!i46(6zPDw!i!P2i;DtwR>UEzQyf_sF&v9?cm?0IG?&5dA zK>|qIDT0Cz7{tQ=L2#_^59EcQUKn17>7Qrh2o~oq61_Bon_PPgcVH&0dh+o3GGLm_ z+D@zzdq~6+y7KBANjGo6t-!Q1IE2^$o?!@BWKmOHU z+g^IKiPRWg`y&cDcy??E zE4RVfst|#R0mxwKcv+_(7EU-W2g0Y%JWjsGTVUB-dYcm)@XHVIdVxU7444Y^04(Dp zw(0}O&{LpycFNU3O2R>No`XU8@ zC%E*1f~{qfR8rGO(4QVOsWXTes$bMIe?WDpg)|4nBfEHKg61o?iH~zGC}PbhqgTiQ zxfD*WD6$Ji@8GJjICueSO9DM>EVyiqFY>PBX2qPgi7cdS43BV@ld5<4ZO6!m--B%V zWZCGHv`F>IoyawyI|1-*+g)V61M(IL-a-XEZL7N|n8BYcXjwa_kVEI{-kMa%UU28rP% zY60>TOx7dAN7i8Qj|_(CpFKW~v4S#*yEM_+pleJr7Am{)CVbVzj4J?J&>W{?0;rpo z!ME$wr<83E*w_rdoVbYIfC5Pv!yXmNGxm&c>cmOkoD(aS0mfADhkgjmI1`Y;k&*XA zFjf9cqEB}ZUYiQwX%afx|A_m9-NXu3)-qn!`M&qP*Qcavqxu%?ePyLtp*$y0$b(pY zH+nigQdmA(Y#fN8bgY1ruQK{09-l{seB^gX`M}T7lPDyEZ`nAoR;RMdN3WIXr54dJhHKCuF3}WXCZgjXEeC+qfwL}&^JP*3xj$ld znRsyUFdtEjmN(#5$XF&g3>k_H{tVUxYhAG?mJDFPxDrYEiRc8DdQy8~27>sqbc62V z+o{=1@3wvDE{a z0J@XbE`i_et~huyI`P2=lIO!{LQY57p_GR=AOGI({hsF5$zS6YUEC4NV1Cp6Z(3q_ zVIkWA>?u7w)S(wA5*WOT1Af$eaC5a#-z@DiD~3zOg8G=k5kcN0;}G;7gA1X27d(sK1Fz6udFAr(RTx{CE3Ebwq)`x2rutA&%g_!wo7l?B_>c}Sk-Wv8 zi)#_pVJTdJ;MsAyld#IzAV+W7mxIJFed){FH-7uE-VH%Nb8GsZ#K9)>??-;*N5jus zQhPNJy{qjtyL>qKvBm-kPeog8dw2}{^I!P<_THCY!iAoH@|(Z0U5*?+atGT!Pd~!Tg&}1kbT|m=Z=6vAt|v~fW)584 zKJm#(!&-~SU@XncgaCr?k(F{EbmosZl-Loa@C(l0;c*jN_z!Neg(p?`#HFs7O)+YFDR>6KkEXY7+gwDFDN^__Dj-;jXZhl z6l~t$og;$>TBJQN9r!92>{O|*V(|w)M2)9*j&uZK4Rqxh_kkX#CU?OoIQPO+-wry| ztB&M+u^lFU%ErFQzaY&1aeqfgaQqkc`SWMD4}Ivvj#zam%T&FQb(*Io$1frCAodqd z%ga{~j^_dK)pr2ew)!Hx3I#h?uMVu?V|@>t)QiQo7sa@XzRqd%vM&lrmiEJ51yX3d zlB!trk&tnvy7(5QI1>BLLG1p!O-`a5-$H6X!ZU3hx#|uC*NaCo7Z(_{<=2O_EpacT z=2|%rW@_*ppz#uSLhtApoGyv0hGX6xg45sd?eaiy)Hx2hRZ70$MHG2(V2()2iJv+J zPx8TK>?12oq5NzHC1U)016~){efc3`4DJTIK@$%w+Lr+f~cL4!a>-aztbD(}n>ty2iz4})HOELS0tL3F}$Q3^wy~mVMsL@ zcqgUx)Lv}B?N!yVF7zZ0^e3pkic6em=$)}#$o`3O$oevrZ=E#yR-F|7i z^X_|`#NJ_MGOK6hDvLTIP*^)SU|$PIX7^{9eGDb#-l<4)VO`>C8+L0n}zdLq~7j>Ih! zeVhnK2@3fDdc(w+b+JUiwzXJaTUQ)@bwe2(wPgsZ<(0P+xC{EyORsGI^q>Al`v}2Z zSM;Z|h!J-~Km4H&ZEtz zDkL&n4#0Xa=|K-1#$(zYpRx_~fO@y5rnY`2=`DBJ0_smSI&6ap!fMCpNY;5GDP?Re zB?n$I_?w0UUSvsS2#R^X_yVk#(v~eww80}Xvdg}DX=n6y2-J>qDmeTw&a{avb@am3 zZ%}TPEz{^0Q66Cm#@#EIq={7=?ASgj@46&D)$phSe%bK5vZCd+1hXad11sL6S^3V} z9b;m<_FW~hX2ef$qf=RksjqcG{gTHwA^Iyanp;w_S#o)y=7atkjSlJuc`l*}#u~X^ zz`Wzqh3&ul@BY#DH~y>t=XT$H_l6caaf2mpH$KZwVY+LF6~Ee~K&?9PtFa>vjrR^C zSD^R!ybg@alCKVwAL&B!R+JE(C)n`O0f~p^Ky4S_0b70Q6i1nn8^lons8dx_{90oS zo45KRF1c+eY6nI#ctT?PPQ)fq!6smI8T-@GCuzpAK2%;cO9t3=)Cc_?{$6mDR6R>B zxwPOUAL&EAH@U1FWL688p01T3CWD-@Z!Wzf05SCMqe0)ek&zSK?4QB&f;VuA>Q{Bs zuiUh_c@7z71QqYgZqfO=~sFYW}L+R!L zA5oVXh(&4fAv#@>`CwC)Y^s>bk=o+h9|sf@KwL3FaXhV};@Bi1vyO8_Ndz~%@K^$B z>tHCLg7WU1yOLOCEF7^Pcp0wj`)4c!I&OfD1u9S+XDLrF&6YR?Py91p?R!7NkYt7r z=*JGUH{dmp?r(4yXm&vgOsLhLf}=2aI%VOfmwd^@-pj~^7aht3LR&m&_9}PKOHXmD zT>Mx&;F+7q&A`;RDFWp!Gg--%XArQ&F~ESHJVqFKWfpgNEoIPEy;CRk)Mx_>O(JFs z7dV>@?g@oQ85aJQzR0#JqR(_ zH^z2owSpr)D~^CyWU+0k9!Mo;OB>ftFm){KCol^g(5-;O2HV=01tyIA@=cJ=$!B)} zshHei3m*ne-}iUyN$hlk=Iy30zj7rd{3;IMjl)U1FSmv2LbV8p^Re3XMs3=<~M$GyL|a&pI+dRdQMOH zt@_*F@%HV5ANpWUP_Jix(R0(r0Ka|WAcd+|F;n>TZ+$uk0sKz6{)2Z)nP?3WNi2AT za^k=kW_QlPL(pj-zahM~edHq_@h$27?F(k2e|Cf9%C(h}xOe4Gipk#b9Z^}w= zS_ZdZ${lBv;GqrZsVRo>iS$A{&pR|oRjz!TE-e`*Kf?l%ii_@wl#Ro?@*o0*?ok^7ORIIf*Mz) zhNfPT<5Li_*xtcw1bo)ixwBHJUi)l!BsqOymDcpolOVPY*OHssefLHsvSs8~$c&&mBbN3bH>&4~D1BdZJz5HIR zff#@IUtiV;*JxOSzIfsM_UNPE*#6>Q{25=~cP8r(PO)aN@2*NU#13P&@#dsw(Aw`9 zDzD?*YR8T3TFimAH+5n%ZE5T>zR2ZWcnO8Qc!X2n2vRL-g;X&$@ z`?`$UAbk>KOyKo8*@AbOUKjJNGk%N(a>H;0iJ&exmWTr^%!8rORqZg!Pa7v zc9Nu^3oQDmE`I!4bqauTu)?1@GT<1dONUuD;=6YB>6im_&a@5L5e_y0-_mcnZBrUP z=OD7-MF&Znu@MpMlMF9aWLSUD8D5nK@R_($1I0=3!w){VJ@l4`x2rzYbO846r*a|< zR2oRDuoHy))LWr$sGMUtVqkm*9M54`eR%+QqL)5RaUJJjxle?Imz1{bIyAJjH%2{x zBv0a-D)S6cWr&3wA&P7pSc0sUyo2wJ0apcs1BHA^Yl~KRps%Wa4^+C_YDjtfIl$15 zdc=aoYmJ474S(BXgt>3H}rR=Qi4TDv@rS{E0 zd0j+KO!Cn&9jSaH-)bfk+Pu1JE;1!DD&+&;ArL^G5@h7d5;(%!(^F6K#BnBWVT5QK zppuM`h_wy;)eIvBNG?72_=KO!2L_}&ZWbYV+YU>~7H@N~=q#NH$O$kf98W#@bPf)> zP_71baPk7B)7wK2J(QD!bubofs@o6y8aFF!itPaf3I4XFK28}^`4AiI$Tu-VUnd{+ z<#XE$bZn3l8;UC~e94zynb;x~y@&P}_%GT%V&no&%+Vc*bzo#UTi(rs`Eg;OHWw>C zRD0Xd{)Iv0!pH=U@Ro^xct@-%tJEr?lDq z40yT9_PjQ@3s5%~oFd!C44C$`%eD z?vCt z*)e3^aZy>Y2RYi-^1?4(xjlZ$C#WSmjBPKn!_IiDZv!(l<(>6L`K)2JVa@iMkS(g< zz7cW!NEKgVbN!Zjt%dqFb)J~|$cI0?T{?f^=(y|vx_jJ**o^E^GmZdE+f*ONF73pB zRV+ORpsmCVy@0H;H3kLdM36Io%gNjVPZp)$|6u z7IJRJpe0^}sDWG1sYG`yNNIRIiDD-2ol1~zS+uA@mS>Xe!6PoF_Q4~&%oG@c6;%~mmELtY)5VZj}$)i(8JrOe)xyHBMjJL`b(3GyPgP`=M!DFMH+nU zG+I3qf6)D_zxu1G65G@L4R21QuUx&ded3d!@b|#J3@ZV{-g*?L_Nx-D*!Yd#{0(W| z6;7PAJvn!nIniZV<_<0gb?d?!W1iS?Ld$QHdBF&emECps-QFE;pHEy;wB3QlFVqP( zlg6=>k=s#wU)DEZ?>FTE87+ltcn6=f`beFNH(zkO3it+3J4qgpjb65kx9djnMOL<~ zY$9hnS|82;I$KlfsLZB1mYyKMshj$=0U(oa>Y=w39x~SyayCmRO2(%o^fH$kn**=L zQeLKjb$~AN2rs`nd$7mHI{8u%Bic^7^(246k<gCJ+p7I!EUn-4?0hl7cATo`ey+)j`=7fUoTb?jNbrkNz2zlxvMVa z6xQ)VDFLj|@taS{vLFuEB$QtG=g2NXg==2e3uH3m?a$W0zFa z!Tynk%JwT%K55sp>;|>3BXBHwVdrTUXz7^CyP5h7_E!1sTRpi`SLt}WKXErA{8itT z%dc!7_`nA|?&8U%liI@Tx;6d^wY~JNb{C54_ywK1eu^C&FtX?w*~Lp*@h&Xh@C3Ew ziSOdrS#N>kK9FC(P?E%YSL)azEle}j$}1)y<_OT6Z0Sv^&6Yie0GFEkLTK6=z%Tcq zl_=C#XzG-Zje1+$V}tz83%=+-2=;LoIKiv#zpNr`2{*+6r)=2Q@AXanU19E2?df@ggh z6unfP$QKE1rT&Do`1CB5;RTVLRYyEf%YYL#XuW})&RtZWudgZrUOJzvP3yo|STgE~ zoP*zzw8h!SWWWcPjJsd7nRS!{wVp7Qju4NAz!Opvil&YHm+DhbJ|!XW zx4!-Do*?qeO>q3LE~;5$X$Ne2p6`0R8(8wade$}+XjkdT`IvS9UFsS9AvWa5FS!&$ z<2RT-_R`kN*2iWT3y0C*L_^l!u%Z_mLFH56ZNI0tS6+T``})_vzJ2Y{uWir2@SG=7 zZ9+IBPh4n&pA}DhH&~=>uy4IQ35Z11WUCx@X(I{(>x3I7{?bM7OWJu5k)qvHM5jy~ z#1S7k&1whSfu9rLCm(-e`^uNUw4F&A_s--*kvsid?0^ql*K^|gqd)ee{%`LM9>>&s zd}MJ;4BY_)M|)AS3@;pZt)?7OWln4Bt6%-{_QaDH`kZ()@A_bIa`bd8sRDhYlO5?gxnEH8Y>+!n$e@GREU$soxM&eOV_9wb zhMaA!$$CDzP%v!(o6g`{{t%rf^ci|n=J7%10AC+X4R6BMojgUwNu`Jn-NeJ zf0Lneu*lMCSdpYXj@N8&d{P&+C;$s z)mO(vaI7^QD^yBHC+j03>1lB`QhtgQptaxG53liN+x+HVAV-&}A=@iW45EpIvY1&6W`cdDv;ol>TE(Ofs<7Z6N68XWW&}`b?QPB3- zBaWw&JYD+;fgC0fYaRf`*EZ10)1I-__o5_v(Yv>G2l_Mhe2FU}UI>s&a zw)ETdO2-jDqk+QuvN{EQayaUe-_q7MUp#@8ygZut)>uJ z+Qp#J2mF%5u_IvLHd01o%8^%{&*frjnDr?+GdFE?Cr?>fh9`ql4e=Sj!R4SS>GI_( z+fz?J?eBhfcgMGzIU%|I!o}^uH$CXYxq9QOi*%Z5inu39>xvJLv-)O27O^%gFqWr1 zd_1@gnV9L6^wQct;M-Q)Qm4d`V~-sq{~fA!Cv`~pp=0G$A6v@wy$jgL^MN(Ccu~@` z&po&O>aYLW_W3V-ar^R@zp{PiGoRU>dWwq!Ky_GBFJl9oJ=bvnU_WKYO{yIqQf$&* zkq^&P$MMl^JO)3g9rSm^^#%LHlsG`6eZtDa=gy>c7ptVte)e#-|1@wNUIRb2ZD7~0r4o&3cYp5K1$*M5Ea{nU1YznqFr zE(ZP4Kl-ou-@G@tz(V`-?O&m^Z&k(Q2rpxdH(Reqj*SO)f*~;vUw-iwAM+;!JpOn- zC-kS!aKaqhge1X)_v)3)+Xp`I{_QP~Je-4x>(vzsZDtWC=P8H`5^24gj5#+L8-8*& zBzkcALFZ{NMVTfq?jS2ea{9h{xdTv0MP6VPh7UW8C-h_-cks2o#uFuEO=!F3%4STmFD>o3^u^2BQ+KwPk)pDCN71Amt$Z4uA% z7C&v57QDriw&WobhBpYPA&nL|u?b#E2$L_IYO_%$xEVLJ8I`qLf0qx~?IX+qQDufs zOIUx6jc6FKM7t>iN4lmDcZgv|g)v|K7lqAcfC>uN^p9vKT#6CJ}!;L@~R0I>a0Kd#F_;qRrYi4 zR|E7J^rTDY&uzc-%fGVy+|T{ocF#Tcx^KFA?ON8D3)_Wr=SQbP7N{3fY=MR~?JrHk zV;fAO6$AQ_+yL-M6)=7Y2VVO?3T?d=Zqa)JM#edU9?Zd8d~uWu^xTS*8mAAsUJNfX zkaEN>Pik;c?tU`-%T2~rzTV{_U&7I&EM>s4&G@Ru_H(p`zWA1(9T(FclKU(vJ&CXk z@05<(heF5j5sFG#1?rq?YvO|T_wf2g_k7ebztPl?6c+95gs`BTj=`Qw!j2^@q%CDV#f*f4;pC3 zvU=%H%5b0yDqp(_fjPM^+QQPW3@MxLCq=&juLGw#Xbj&TDRCevPw=cK6+fLcgWa-P z3Tv{$ydGyb(A!aCY0%WO1nm|G6(1 zWB()g`t|L4#?C7*zp{Po!ym~`{e2#!qD$XhX|esPcXQEB6!;zQWA|`}Q?SEnS$E`&6JAKdg#!Fhu^KU* zT+{hr99#MWPtplqGxZfJyLdZR@v-RYJMi-90!aJG;hH{AuHKaEQ}VQP9gyxke4>}R z3{G_5$jrb(1S}#MIOZQa2dKpB=3$tRfZ!H(6qtyMK}0r1oW-yI!~#pVCgMyajg$~ z*XKa%3tLz^6iHIo_+pZWb-Pgh;Tv#SWE?D9corWZ_81q0Cp`IxOFE&is6chD{lZDt zp-pkoaAY6*0gK0D9H>pL`(A_Mx+Nc+4g`bj*yS$SW8Zvi`}2SP&pZFA^Ro+h@4EX= zU$8e~g=4!Xd_M+!VSB`IEH-1kQ02@o+Muo1g(C%kbNZhJx6-Fyj=*^NIjC!&wbIh` z<3giDm&+rh*j9j+N&4bI2W@s;89Bz*8Xs=sz~Wy8==z0n)5$S)5D0|6n#U5ToV*Lk z99$=G@FFnO;24ifo&5%%CQujhJmtsxHl{iS?G<6Y zc1h8%y~W3N@eG9Kdfnnqm30Al2@@AkLDYT{it|-In{bI9gTqJF=*n9t{zM(#5vQPv zkr${h{=qL^@xdMJfh#j8*LLtM{3$FxV2v3uJHG7&%3JB8uyeFFCJpNj$lik5nU-GQ zgdc2D-+f2Nfpz4Y+wa0j?h z-pL!i^lv^kd~musZ}3827b)(Bp5A`*)1Tg6$w?dshKSKFUXFz29=)=)T|eYc{Nl7TI`|NW^2=TM@SQ?_)-zLdlt~A~deX|%81O0&33*g3JZ%JZ z+dlsIGFAcXhmv|q%mL~sU-~BBK^@6PuZ|4ZJPIN7gnGqul#nIW$F{uUr7yMvjPk+T z>LXpoaO|w4R@OUcl(9oBLf!Z2aE*P&vvyW&gpP4^Fvfg3M9CyVO0q+~q_H@}K^nx96XKe!J(cyIpHoLs@&CeDdk-rJO|gf;;=P9u-ozJ+BARACi78 zHv_l(q4GYVuuw@zoA6~q+;tdyC=(mNQtBP^6c040?f;f{zpX;6 zjdfx6(00n@TkAi(>?gTE{Ru8q=flr=_<5Qq!?f`RF-@LL+e<63F*XCmXkq|c&HaQ> zTBF!<+7KO^t?7aaCdMDV}5XAjV5HN=n+b#ijt0zPe_4B7Zt3Vc-7t zcd{e7);>Y5rR}b}?$R$){Ann&!6qqc=o8f~f0He~woU9naXX6g2|6C~2~0bW6^NmK z$;U=@z*%nb6eI7!LcV9toZ6mx>dEcv-}t&^#bl1J*@<%Te3bBf^IO4BC?!xf9We<*`CYzL!@!ZiRtAl+s8lh z(d~f;9>^HGlBPxHIylJ~UT+LOfBr&rF-ErSi6@`fzVXf9&Nw^g7(HQce8319I0}rL z^)j5BuW~Zn-?iSjetrA!M?Mx)wDYDv58&jX3%$=&*sZ5>=FRakVdemY$LEPk0e|b8 z_V=A5_yzT&W1LjpI*HIpUUlWO+F<`G58ol)&}8bws+>;9A+CMZ@(4vLAKD|Ky!IXC zu^|_@wet?%y1J8xrSc0(&!#7kJ1zdsT;s9YLDE?wI2?!c)>dA2V33( zg2nBR)bC10Htn>9;@MxIt?dR}w*u@#iUHya6-~BX;%3X(?*+2)5&8)8Sg8A{;Nj=V zCg$*8{xAOW_O-7+y4{}jj3+mITr@oVT!5T4%oAgA%ZhaYOw=bQq|n{xO?*!R zzun~GMay{G#PLOPVk9ity^+lio$`l-)o^sIghkqZq$jrBH-Sxm_|eo_uNSlouF|Ow z9UO7pPx>-vqJ2`?}in!ZeShLxXX}X!`j^_FKFF>++S$*rZ%aa}omCP$7ez#&!%apa>x{o@e#}_@Go>AZ^?g(cY0NQJl=P^<5a0!OLG7AU?^M9Kqt)`%XH!=v_xuwhT}_ z)&=E24U}OjiAc(a6Z;_znSJ7VhmdlFg?Pbaop$9j{6vyZ{c%!De*<0%y^tN~LPZ1_ z7!8?`HmH=L7w@2Rk_?*8OJb*P;QfG~omHwPhq0KIJ&!$rv)Th&qw@ zI-ydRHxS;EV`=e%8^5fBSGJQ%96nC~dUv%@x$wp}@#umrIs7By&dY(DM#NK;Z_hmQ z%=Y9HPi#*<{^a)5<4-8hL8uBbjc_!V8|Jd&RiqK>8_l{^u5*_H|l?e4lK1)e93m{`}3yzPVj_ z`4tcDc;uNos^`wor?mIRb}e!Ep-=tbcK`ivnip!com!fmB9oFw3pKuWoY?9TSnzke zw{17#BrRg+$J@uh@|7>=1pI6~iXv2I2Y&mdOWVgk`HAg{cX}8vsLKwOz6y`i3jHjk zNwnjOU;MIHzL_r`q~Tb6dG!XpJ35kdEwQl))bVn$r;d($@407t&%58_K{hV|JAH}^ zIuSeu1Om1d#{<@J?LN@rXOVHpe}OSIvkMVamn~g zEkZ$5f7jMsZAOt2&O`X1C8r#D067vUFtUv;c%?(@f|UTUG6KY=e8A#Gf$M9almhDm za>f`?XJl+s06o~A*n*Shq${sl>tJb=Nw0I!l9r(@rEZB$Oay_$6bwnNXU5^Y>S8)(CS_;EVM5BL|YhcR$OkvTEWsgAP)8;=k zEZfLcFC&~dY0u87T5-}AIV|MUTLHrO|n1zzS2d&Tu)&eeyFIi+6oMF+_k(spzzlYYoa z?pq&u>-NwC4{uj_hlP9`>)iCElG=|h@5%xCoBH_odf*(=XV_DYO_!`SuVq35I#?U= zd-SD#e33|Q&Cu3>lf8PWuRhtK$d+T+HHuu{*l~Xg-8Mps1bpEK55QZ^$?ccwa3rxmNgcYeQ>Zb(o)=7l+mBs} z?))MS#4DIR?g2^@y(LlzyCOl>))*n9v@^>zz{UxkH*@i%%!`XeD?C zIy5>)TnAGJ4+jt@42}Gh?W&;s1Rohrm`cXp@&Wrx2t4)}OY39|OnECjy!a$Th6cV4 z;1}QyM3&*%%|tI*;ILRN`zcME$Sz;Lyj_0zvJ;k*I_?V78t$s`7!5#J*9#U{0BGYQ zk36DE?JQ$JZ1u`eiew6fAz$LKFN))Hm4G9sT`bdK#JF6#2y@8b%Rt@{r zE3WPch%b;U2%91XTq?w(RP7O$RR=tHRu0@cSuc&k43+4lTwcZ+@nCu9vA{2U@e3Po zfySb`mPFcoYB-c?W?DYw6ymltw$%@}oOZBl_U$_}r%g~!g|9Xm5dDqEoa z?&w%=2Dem1*yO<>dDV_R=+&pr#H$C9m1_*=;!}L%QWzXMOx3Y21~5k9Z4Ad>Wm|@K zS4GUJ;1{;+vz4ev@7Pd>sMRlG^~MOK4c_76!dQGccjin^h9eyl7jx3<;0av3cyaru zzxf;6U->IPx7~639mb^le=eT!+sISy`+!TgUviB*v5t;q4C@m#aV-mu#TH)!;A!iv zAph$L{XvRO0vhcz9Xr-fdFdcef^U3SIiUP8`vPJPZNjiGKVe@gj$dWB&TFKr~1W2|zl$*~LbIC=JG-2Hvq+uoKjd~v&WeZ9z$W4E*0 z>5OwO6w4nxI>&{bZ`s<72TG!M#kzk0=$jMAauD%j`~jtGHoH#rWNxim*9$<#(8z;J zZd|6Fh2fP4{PHy=S;{9)o@0P_ib8a|uPi^@?T4-bOD_x_4^kDE#CWZQAL6j{&&st= z#Z;&-Snai)qi)w5SnXHekq<*Y-~!dL6PhW%(1&q%C_p&LD~uku4S{Pb9O8~`k&mp| z?gO!4+j8;A^JT3jR#f&b58Y4dK3*=qGVS~3Z@}vVF-?Ga6<46X2kn3(!0pqcV8R;$ zS0)M_)csIB;spo)5y~mf!~mHj300$xH3E%-vhe_>q`?MiZPpXPF|!ux-M4ZwwaQz( z6O#`*5mZ)!c_(Q>z4#dvkF3fHn|0m*{Yp+W`qCkoIEi@ql~=ak`_{L1-L&;KPHG}^ zBMU8$o8EKhJ#!Eg+FUJMI{eL_cX_+u$`ga=@gxdGu-ZHAq2l196pFfON%c|#pt~WL zlPuerNXw6PKqhOFoS?*pJ+6UoE&A~-Jlr1#MQk2_{BiFvRIWVSC4BIq2laX_nmy^_ zBr*`*L!T>XwtT= zzM-4=TsU`T`|4M|>XQK6QQ?3R9UN40$CnuJ$l!-^0(|L?OFov24_G7zJYeK%xArF; z`PFn1dXh-#RsUz2-yEZdW^(ua{`>CTKKQ{8_!kc{MxT1~@ro)7ba1vS?V~Th{`E(< zmtJ}?C)RKQ&GE&dpdM6dIQ9|`8HimIoyy5Iad_uD-xc=u2l4XdIVfN|{aaPVVQig* zib1D_%h;hZ^-0J#9pj2GZ?qm7I2Y2xcXA-JwWgVkSe{4lB zGQ}0I4$Euu5M%Q2YG>jYK4K&VTymh&sS%fS8s(*tTpyAPl&7vg=u=k-^_SoP3l}Pb zVQ|P6DB)A`B=sQ@KbGJ4EGIgk$v-r{^2icM8R)<&jQp_=$eUn05?5+)J6JAn+pA~Q zJGeuOs)_Dym%CB6)zZcBNmXs=bzLof0ZjusejTU>q|i1QgMj*sc!%f=jxPGtY}%9ZVvmoIOpczNUbbNcB;xtt7#&EElk|NBpE zKm9X5;|0v~7tWywB{?ZLyPZ9EHglf2%}GQ~9LBz*lV)h9{OGgK^`mVv*>K`U4v-&} z_i=hm4~ReJ1&+)AY*3Q8Q*s~x#0!5<>U3;O2bst314qm21jo=a4)%6WyjOi7qh$(M zJV{${i^$GJ-+CYijGA$;V1)$F@Zodt=oH&VrF0bgWaXZEV2#tZfqL|mNw9yDK-uT3 zJb1uzpz|YT)RS04CT@#o$q1H9M-CtCuYm4ASKaWOWEZdBCWtdGv*D=(o>0Pu<2Js0 z^kW~jUmB;{^Fo+9D-U#E((=k`X8Lk)0C;mY>ZC%ui?dA%x4c06$%~5C_)K&0RXm~G z;UI?xfV{iD10CpZOjm^s753e!AV_Yv7r%HH3pGmj57b6f(+cDsSLN0ofrmyU9AH{d5zD>e zZ+pQ-Or0$7*|t2nJUMaWP7lmM?P1dvXrzV){%GOU4)*ft!LUeebBFTk)oa`1-+RLU zuLU#_CVoryz?&b)K^FH0Bd7W->xthQCvA5K8qLPXK-w;Cga%1+pjS^3Oo|@C#;8o3 zvA0^Owk>iCmz;Yj{N)dQ$cfz9)11`O--+K+2VVlq@3pxD`?=45&c}Vxha0^8nm@$i z_es}sl6lu%_ii8k$j7#8{H0KMXzTUs{08Y-tj$X|X7SaJ@X*|2a4f`u`YelO@DDxo zkiYxA{K_jH%{LKg(%!U#6ZNlrXn_?CFF zxbinC>#oD0Thi8>ncFu~iL;Ca=v>F3T|DZ~lMefD!Q%&Ie86h$;}byN1#DyR0v6CY z%lnQGAZC?zlw=ioutDtH`b_~0h1$^9vNlq;f@s!lWRMLGe8!6H%9zmJ@UH;kKpnq%TL2fqWh?s2OPG{;x1rUZ8ACw(R*x-fRG-AY9*W^v2J$!?jD>h8@B)N{l(hWh^vs zmeOzfpI{X?cx>6wg(tT3LmV)$)lu0b%H*^cKaOnGugIED8GXivu_>1{Rwd2FR@t*Z z%bdS(>4HxQ@!pC9J&TtEVR9;8jF_8u>4x(p}E$B0~U`BYjI!?*B=tf9=*=TmTkkaZu{f_ zyYJz%4F9xMin!K+Luufam@T*!Z8f?$lIT#FF)Sr1HnDezCF3Y5B=Lqe6%?;Hhu3#R z3_w2MM^8e*MO|RoZ3X?s`8y!iD&$uRKq3MAT0oZMu^)KSvUh}2i3XB`r%al;~We9cB#T zV-ox-4{zuBN;95dgSLjQ%4|W090f8FFk47A1a$*p4(@nKJ&t2P^yQlMSF8 zp537okNl7xe&W}Y=j0x9RkD21ZKZtt4%<4sJqYmw*k|G2LnF|aa1gW9CdTl37J)L7 zo!T^eZ~15#ap$C&eml8u2oDWyqN8Q(cU;ky{xrZaLeDp@ z?Yyp|sjoTJF#})hj_>vt8s|wJ=sku^%gdr)$L(m0q2oXLihl!6LPl=~A@OoB6WA41 zf)3um(g^_vUGiB-JV+!p-odp~_D(}T2bih5fT%BN-6lN|vk~ApQRLzO%jX!VBrf?p(2d zJ@I;LPL3}6m@H!uH|odLD~Th1VFdlVzw|o>T5o?5Gb`B;r#bNj#@;ZrnD*nB?6#La z9sTMhhP2sM*uPDEBdRaQKsNsMvFB7%{=%2OygmE{ld<)8$NN&8DoRy0U2b1O;~X_=uDon{gAx=H?BLc ziLG7-Pie-|3VM(nIJ!#}+8T6dO5J_4y(hHu1kBP-;xXvI`Tzdg+b{jnFK_qUb60R2 zxGn!{gZ&?GmHhmSUVydJJPuvH z!KpF6DN#SrYn$!{e~^JB+3|W9&(KGsb&{e}KJWrwY2fdT2T82f9aiKT%sc=4Ug?4sTV^ethcs12hgvsn!BICyhTGAFk+V zql3q~?Io_L4O)@loD|80m^)7(IPjjRf=_aA z&jMz%g)Xov9ZyitIDeYM=?mVGG*-UBa< zp|E)+%=yTlDme91%A&}Q9vj?!<9}AcGw-4jx1am+?YhRu^Bp)A;*K^W&?|t`fKlzhC zx&5m@@e|uS-|_Z728}Etj*mdbEiY@s*H|ek?cfgWm%j9+kmtz|`#VH7CcgD)`41ll z2w~PAc2dNKyV}f+4}I{1j&A_-#EXjw%IB;9!INqRn-CNc-;+>K^jQgvF?r*oOatWv z4mhy2v*h8z=h3_H`L zd$+>2Qdci<)EDwmnM_>yJcvluVNPBrgCjwgZ2&oJ6q*z}7ekp+c=)Op{SZf*ih5HwE(du4y7lD78o$BqjUD`elE?D2XQ!vM z^dv2|UW6%aG`Q^{*g<#2Dr*KD3VzkO%u8Z3JX0s5O*TP8rPqFGjFCRcb-Zpce%V^Z$r7=?kMN^lmU$tx1y~9GvZZ!yUtZkTZx;; z5DZM@gX4r3nHOJtaeLqUejq2xXN}8xp9|}kWe4-<=Yvjdps4X)DHuVrIe6Hhq`V); z49GZXNR_2NiPk0-YB<_=>5y>DyArVIEp<*VS|G)ar=-Z%$Mz*9HYHmtj2&>LQAW`^ z9!=4Hqm0k+HD$vWbV1b6sL-}m9$hIJ+(jN+tVfG`#D??BD}C@$6Lh1HE8J zCpp-CfJ_0~dk1G?v{V`_+H}ICax4RVIlPoEJ%G5jq4@fQ#cngBzlw8|Ke8*)}jT_GTGykSC^2RF3}!~cVcq=$~FJz7)kGd zK-1A1IT$+SBXZ9@^Q>210piZ%Mmz?7@4feVx3K&`w4~p;Bk4Ixl70*2X&h#ea1;8J zYa1J8!J&k>1iz0n%H{19&LbceyD%em0X9-o1w0}hqrAoWYhU}CZv^*(Nbvm6F5pQl zvCA0v+nq4W0=cinxrC+CKmIhYJLkXN-0XsUlF0sW$r!@stbAv-Cfj>Uqnkh9@)7@Mt2 zT)Y8TnM0P2^e!DU;Xn!983Hq&EX&-o>mAkAwuxQhAo^%~ta`P<*vQ+H4AJ1>b*%^@ z{-V|P1>gBX$~N}Vqv;e*J0I2s7)BTJ<<3qr>V2Ry6& z!14N>L4=L~yloq@L5zTRG=kR?^-`^0i?35PJkeX<;^XjwkRMmjEo9yw@zOZT>%Pil;iFn&alI*8A-i@dQrwOu-YY5V2HGU_`8nwem`Zvky2IrEO? zb%(q%D`xy9lIYtU4aq0QAS*VI%4BO+%a^gT`vHyO$iqh$?)GO~4YzW9)EuOvUi)NX z)#XrVaR8|Sk@dO5C7UQxI`%w~56zg&d|$^eOChpcwC#n#8Ry|wM`%6CeRcczM?ao* z2|d|2o;kPkaASjgTp>E5dtKbCqthqRze9>$`=;+hFSE7kb`l20PoQ{Ei+4fFW1}=6 z;~iY82OKbK0Jz<3eBodYUOuWTpS;<+z=YsFD6&3r1|PIQ?LZ@^H}N%kJ*ih~ag4bf zlTxc&*a6pb0IlJ-rR4+df)|4a|8I@MigRs=i751}kHiy)0mjHU&$us?mk-7oYwV0z z9XJAzfm`v)RA?uuVEB&!G`zP`Ut=oZO_pJTy!h!B-oeDtA;)`!#}EN9+HcrG9;qbj z*n!~i1zpH{_om4*b(1Y7)->jPtJrO3k)m!7$9enDZ zWT3xCS_dA~+80dm^_kexF5@#h1@Q2Lj}NvjbSORkr@WxN-BBPEvL=TIpK@TtNh^9> zSZRF}u>(1q{JS}^dgb!v;PAt!D*cv+AKWfpyl{x4SPmkihxX=!NV%aCCs>2me-aFp zbMcLUJqk*0*vhl6xZ-DZ2FLGHV!JIXG#=H(c=m!tQ2a)2J*tVck4L4z%Va+Nna{=$ z{a;T}!MkLrUB7lcC;RtqAN$zH`k1#Ia@k)u=`-@2Eb!PccS>v12*i!}s0d?5rP{~o z)b7X|u(adi8o+uOttI0>P@9{tK!`*OGISN$z;&YF}{9viCe z__V(XK>SikAV%v}|xTl%j&PIC|_c+J@{p zQ=fT*oLP9yD?cqMU5WD2rWIFg8THu02Ynm8SZntWFEOCK1CS(ZN9{s&fJvSPFA4C> zg$lAk?-6hOG7iGQ7viw~AGl9A@OLzjkcrNqswGmc6Yww#PHoU-u&$yYa_ncZYLP_u?J)M@S3*t zcmqG%9#y5N>-fao>Ch}^uGeR{kgbdY!jusPZp{Z24@z4UhfdzLU?tcH4z?(19c7H19BEe4!f)sfVdXX!y1B4 z`s5h2F|f+c;~A&w&E#O*^EA|*cig$X^Ih-AK0GwqLqZ05F8YY?6Hmx;%);tsn~0x` zwIhU&xp*@RX;q@Hba^NDqN7#{@UZl}ft_~f4`pH<>-r1|UDcpg+M{=)Z*tN;M#U{UoJ#7~kkxyTHxnlWp`_|o z{}A!gPQcKLjc@p1sX)%fLXPQ-h3kL#qEx*wrJc^96ut1H()Lfs(i`x4kg&Bw?Engy zsEivTYhZ&T$SV!1Wkz=r$sV zJK(4aDkp?jvCw2+GLnZMV>_X7p{5Qd4?alB(x+_};9#gj3%|b~<^Ni}YwOvicZb)T zf_bFuzWeUW2~Q^?3n0Iz(nM@{cW@fL+S>&M`$gDa;F#>QU<05_3ygnO!Go*8P8b)6 z#mhp|wha4HRvr4&_NfEz>=a(jiJQI!=la29%!Wt2fB*M?-<=ck+yN$F>@XgF%fn*< z2hc~}qS=v+0zOgBSfEX|i*MyU0TY1@%9V>(&6BAidQn~I-PXlRHr$hDyaxD>;L5_3 z)+X_|)K|aC8==3yojJ>88jVQf3Nh=@<;z#L4}9Q5+u76Saw5&R8GAa^a^0m}l~W$0 z5+YNz-Qa^C_c4JX>J$14`kLH}N2b8g;XA|Kb|@)xH|OP-U)jF;^+&g}8MnSc+p(-j z%8|<;^x#_s*`&YL!L(kIhnW+2AOF7RuI+&b-t3)z;?g(B*C#oj?^x@z{(*v{wro|nt4*O6fh4{uGlaItS6a`PHMD# z?brachzpO2dXRhjM+ZQN=xe$1aN6S{5)s;<{-O2Yh=VWc z$V&;tT4JU@)|(TX1-lwHu0P48W3RE|C@s|9Iz7sS&k5wlgUUfASaipfLL77VbV5Ls|5 zjsq(WmS;1b36$0eDNRwwV3(cX)u8Q? zY@-H1hiZSOymW#~vIm#^f*HTsQ>eU_!HF&p^Kb1Zr6=ue2%wjJy8KIS!T18K7`pxi z7_aE(NvunkF78h-sXJ@!m8-nak^Mq=u}O};`2OwxpqKN{4wDtoG<3%9u=D zBUW^=YG!{ndb&@7KDy*>nSJkWJ2>%+Px(ZhDs#!>tl+|5A5qjCx#gezgO2c3ck)r| z8o2P(p;9MDzj{(R-hYS~+Y@V&?b25iRoSR5P8!U}7UY)?{MZtYE=om|9+1Dhw}KoM z5|kkgj;#K{DYvkT+`=m?yGMWyTd?yk=0cAxf+w*-#a>yKI}X72!VI?CFAE&U3y>Y! z9*Z~NHNg4EbVw3$GFTJxWF5pu0i1ybTdx$A%A}^?3C|AbtqzIPp{v)xFVl8zfD=SP z-0-Wr3y&}??)>4Au&D884iGCpdgV=FaMElT5t| z3ezt~yzWfMMW7q@iH&{~8mrn{irJc2SQl$@itOm|>ATGYF@2GG*Cjhi*;=7|*r7K@XssO?-SflFX6Xcn{EF?4 zJ&`kqPyv0#381UnW5JE>>cMWXtT&p^hIts-9!LdmJ4RkSZLSYWgM)8$3KEhGQV#EoIjmnSaa3CN2=*_0~PytLG_M#RcfQoK{ z<+Fe`U^}HCk5BT{J-oG1c`A#ag6#*Fto{~y(FBIpm0`UMud=|fH#DPg>DZY9wrlV) zq|c(jCCR%CmA7`97VIZ7$$R3O{Yo;{Fy&zdJ(>NRn9vpyKhtP0H3kKAriS8EulhGf zr!&SbT)eRT;xGI++u!_~e`~wr&O2)}Z0w(Sffg4pm^-=`c|OjuSp&Se8^7rH_Cn#P zIYRxUowNbZh5=*1;_uWQ1?4)9jf|@u$1qjYsSCEi3|zt4ywvT~O+>I|&l_ z`bU~9i5PWk24q})G6@=)VXQ3t#N7)Tu!&^h5Rg`J1$F1X6eH$hU0>$MQKy>ka z=QvUi(B5TIuE?!6=uwDGaFnw8iZQIge!;j^hxRKws7i|-dHI(;VB`lD7Es*)x=H9} zE#rv?0JY5P9s}^d`j@wdA9`@R=iYm_>pq15SI0K`Y!`7%U-X6q9)&>P3@rZ(M=__i z)2I_KX73yag^_+{&g$o^XKn4s1z%0!)gj6*K;qYa7C^`14W&5?okI9ExLH1Q6jt@t zUgM1(2;s-CnXAI+SncY(uZ-XYR``=tzt)4Mx|%Zb>L7)Wb}SwQ*|NSI!C?LHg}ePs zE(_=#R$Sc1)?OdIv|&GnIO@;(RXE`BYhW1@!kcP+DWIWmx%axK#38yIJoFU%*jjeHZAzZ%Az*v8(Q057`3eZEIPrhJ8$CU zO=1EEZ;Vss?w-mPR3yAwOTvLEf?d4BgE=hgruw?GIJKSjWQyOI^0JfyC;J(0N$>l> z2Xf-YZ_E0^qz1GX1A0;-d(6y^8AIBRzbR79_Wd@z_47El#1Cf6h(#)g8SNc5SG&d{7>Hzo;j{LWw$#qEA}# zv}cVQc$X#*eA&`9ZdgwASJyVo!gB$ zfV@=l6gtN^A!^;ffJ2^klp(B+T;=4WVWYRr9QjmeDq;XMVJ{58vv{X&g&e?kt?j(f z$ty=W_Vrz?{hH=7pQabD|6j_ z$C6m`;ZMx^#_;6<2= zODOeg*_Xceeed(aJ^yo$5A1Jwzls0efIdQ!oZrA>>-I~Rym)<+p9#Dg94y3I*)S$Y ztc?(vCNZwV16dYu$i#;nH}K+0u#V?Q@9iVr`BZ|ssM)l>a@TD4o#OxwQD%Nfiw%5m zKVO~t1I#%#(cmLK_v-Y>t`hTKfK2vUcSnlZ08%Wfaz?3Ip937GB~0R?6Erx z{>;vW3Y5V`X#y{AK0WvXmt4JzH@U3T!80I|A9b7-kVh|k!J$)KJ8$cN*i;MMDKf!4 z!H6D6u-3%zl9pbI8!z?<4MulvU>Wd-_IeNkA+xv#OWSstzefs<$6{Gz6wKFgn!@Q6 z+&RM(nY-_~E9$fOhEIQjX5$BcUGzX6KwrY+psuF)iXF;r1Nscf@Y{~5+n?A7fxD3W z(pugm06L4dJ8Oi%k+~oP%SMWlgV)W-P}ElJ$3O0Ze*gQ=cmM^kYv5qv;)V0uTXIs^ zxF{N^e&{{0kDcW1u!&`uYO`%w&`BK!6d!^(c2+%5)2D?F#`cQAXMAD`Bu|EVi0I`& z@67oe{0%RHJrQZY@S?9rzxs7~vo8#)7dJQwWbxy-Mcn=V(1$_P$G3Cz6@hB7!aU;;RtHaY;b1%slG^l7a&&X2|IPQm$^R_&|A6%w?)rM> z9KU-eR;&FfuagLL3bY+u>xVc2*abJf;g0kboAP#SG;ge_F#qyd?bAlvRiLf)#gns? zIYb@`HV|45@*>2XlF0JnnmZ>Vr*ece^NZO0b%BDGDH|-R-kvp zsLOa4N5ptrJ|NwG$SGkeUAHA^4~8C4q?&Azh{5s^&0{jDHa+R5jYzC`4KF|$z4Au5 zKEEDJ|F*LGhJ5!Cv3$(~)3DM`e zf*u!|Sz8t$I|$bc)(`Q)p(g{>7!z+k;2=j;`vG_8|L{>#IPpQHcIQI;4A{;of(s2o z=!{t!7@yz!p7&_C$0PAQJU#v!AH#=T5@P`!)}v28>$3J;BD6ce_~4=kKa1)b5t?&1 zzQkF%^zGoI^Hkf%0Oz#n7>?}LRrpp4V*G&An5B-Ld~8cnUt}j+AoS_OuIa1vE>fhf2o4j8Ey=7=nbNH@M2* z628QqvGyx0uHwt{2D}zB5*eIKs0mQAJyryiNqqD%sC>d?9eHPJ1HE^FIvD)c0tfja zW{Z5j8ca$R4*2X;2A1;0lDu0s@`d2h!CpQfWfmg;nkeKBvdTw8^->#u^$Q>5W6@eP z(B)mZiuE@c>a&_~HT|0Z#meHf`A7{uGRgOWsk$yUw1KPbo=A@_ulS{|F917rOlocv zuxPr1fFELD;e2VsEcjit(4WfK5Qt5{{zE197TG4&N8Jd%F7^@1g?A^U&Mf-+T{$6m zPS~D$>Pi1PXq}9f_ok1?UbuM4JEK4kZbx@yiOEYZy_hlFXU=lMeOBELE^s-yKA)4x+b>?+ zE?vB^oju1B28?XH&L{mv8*Fm|(cfD#9zr)h=wTc}yS{z-i(jyf>tve)t}~3K?BE-V z`h$yBMK$i)Fvj@b|5$wg``+i3aex@AV|+(ur9$(4en|t-s%0Y2=YdvnM z4e%*BPhBfOO*{bgtoEyVASH0p3-lSXsv5n3s=%4$v&QlObm!RMcK3kMwGK!v+pd;f zQD%-{p>#?zAMB7PRhlAr3`3MVxFf?8Z^bI%w^;CRuWbL9|NJj*zwznV9 z9hJVv;%rXXeCvGN>zEEb>qzg0r>viqQH*xkw&h*-2i^C<&^2FO3*!56OaP@;52e*FN%5qitAQ8GprdaUDE=NRZPrlB3jZ^dAZ&&Co^5lX^e zXNe_#vTg|>Rh~9>90};qRCRYO6$g!S^Vq?=WU}m z4C{jpbTr31)E4h=Y8kW8)xGIh8xIW!uJw1HOQrqB|#`mnAvlarm)Ev3&5{ zim#sHuo@U1Vc8ETOMUqkVD2<_jF;p^k4$Zti=rRVk#BNX#fyTs@e_`HcmqyAudf*N z6{Jp9>l4K3?@8dxYZh6>LzFi-mMu|7U>Cu-6VOAB{NNWVlg}NzI56V_kbzNq2cW}Q zWE>O#BB`?=bhr#o&U}=wzl+zM7XvUKWkHAD*f2PuCq*YB9l%|@UV8cEJ_hQCli+Jz z@T{RO2O+LmN^bYwbI*3iop%I>OkF5v0GqDf$)~M7*a=6HygDbd^vc2rGPUIRXIr6& zPp*sCTN3t_ThOyw3(yK`|XL-lg z45a47f3DW!fBTV>;xpTqa^m{;{?6aoe(@Loo9&4wpNie}cIvh85x>KZr7df(k>f9Z zKmXjb+hdPC))!(Sm&90K2ep32Hd@z?e#IClFSHxB|B-jRJ)vtn0OgYt7g)Wjua7|a z%3i$s4H$OUK?Mm|a+90gLL(ddYYx>OewVi@B~TDAZTL*;D371<4Hol!sxBJ}NzgA_3G->(HXp8amkG6+srY^NLU0m(Ai^k4Kh0 z(Mo?D?#jTM@{&2)k}Z1zdV=sE4E~YXVbJg+W_v}zJK4z40+^YCz)4>%Chz*O^sEE9 zHSQ2S@UC*P6Y2UZI(1O!QD>`cN-JKFu2idT$;)TClU>=}mTS1hf;y)Rj2-%@XqZX( z7)*-et$fwn{#tY}0CoQ&BpAjF2i?%Pu!T(yu9(NX=m#K8ojbev zo{%(z6JypxqV?SK&ul;OlmF`Wuly@NzWv~*KDGVvKk+BF=dw0)Vs<0_#J>=rgWqg- ze^nbovcAla!jZoerv1fHB}Vkcl$Q=bSt+przO>cWwSHI&8?CcAcCqEK5ZV_-q|eJ5 zT=lPhDbEm7@A5$}lcIxchx)rNuBickNRkhBv>9l%wg7m&U_Cz2C%%C^EZ44G-QN7b z1KT5yywwXti+`!a<=SH(ODatrn9yhL{-)1-!Xp^>bxZCx|9#=vXP?V{_l511oCpJz zU4UO%gINbo5b8zy%o0jP%T?zxwxFT|zM363cT`g|7}aer(X_(y%Z3oqq|fI)RlV>dlvhOR_K33EYa)Ge6=ZyL2tE z52w7K>W=l+UXLk?BUe}Q<D!GFug-;E(2gzk1YjRI z@Q?=w>yBR{%7d?8SXm;+P`iuQOi)d9xR~#{hLeFQrU(yW;9+sfC(CtcT#fDTe4#mw zI8aEu*irGq0~RH(Hs*7RNpk)A_U1Re*%O)S$M)p`CzLPM+j05Or^A61b~@ETHBDqhtB~p?BLmfeE*qeaDpI%;Sik{p@GAzx((9{`RGuh=2YI zU)=uI-~Kz>_n&?yuJc>W*q@<_#0~l>@$Z2}^#dH(G6ui>t>53S#z#(qF-IHuJ<`?d zSEHkC_5jz|L=YazREQPe*zC*U?z{KC?agm~v%fzq(1sjzMJI6)GbeTEIgH`)P2G_N zJy0HG7SELB4So5+3>+NsRIYvlR{8rg7bIerNuw;_@EAW7R=mHzlHcBZ)^3X5*%0c-3T%S8@`HMZ$+bmY5qsMG#4IKkHs zN*Jji@c;4cxXw}fFEad` z$P+IXI%AeHKb7E7&Lk`Vnj+HL4ln%d|3I%eP$qWx2u#fCl)}o$|ge(D)rtFtKw&EQO5Y@Dby|Amv!ahW%U$<^5znD6lq%emg~ATzqq~cz3=wp0gj5*$jXXLo13sd-aeDu|RAe%mheY$2fh24{Y z3^qFsdjWyR|3CcU4{aANob#qe8L`tMJov6kVd^4Y^&%6%@lNm56N9!9p6fTR-h2;n>-f_7D42$;|KkBpTI2nXx36|A`Jox3$Krd!YWdP}u zye%`&{jIwAB)*gp5QyIt1MBZKJ0E8LXCgSK6{amo=3A*WgXo&H*An3pxXO;WX=x3p~7&#ulBZ-WeFX z568UA2Ut|iK%v5kK;-es(-rU`hgWgs+Xhegg5+~(yUJu?5;Nq`SKjE-^ljVAue_8U z))jSgRgK?&xQIl}&Fm1deDU^6j!!JAe)WQWQo;suL`+I(^aXaftJud|(M!DWk=Rrt zZ9oC_g`1){_Ic^yKc7NO}6^|<2r7@)7ABcxBu zck~g5^5O?y@y3`wFaJvTU3|F1!%vqufI;uRlgO9~j!@dc6zY1C{^>c)io{>h_-Zyl1=XuDcx**uxVNbax0~Z67+&+q^d8n|;%^JI42`)SrH)VVvXh!i9agiWcfEm9 z7S#hOC=VaKF?E2o0K7Qr5RQB)P@Wbutg47wZHM2Tr3VjS#}9Oljzc>jL?42-rAg~y zP7^5A*YN|`O%5I2vNSf7mo4>mhzZ7%zD%9|v9BQ{XIxFon&jm`G&-;a36Ah`2@9D~ zTcbj}r;NWNv-DH4FDY6pT@X(NouflYA%0X(t?BdV*=pHac%a^Q zWxVRe$xnagx3-`Axxc!dIdd+!u6Mn-8`0=s4M!OM%;xyqF|F}1ScZA_W%6Q-bwR#R zl`Y5YhRj2RZ>BR)j){yOiE_dm#WgWi0{d@oZ|9X4y!3VZiu3R=f_~3)v zzx}8FlrJ*l$ueZS4kVr{rgfmUD2k&D0@o7@@IwznveFi>=vl}|I)Knp%mAgm)wiI& zkP@f;1U&tl!hXSu*s-`Y5J~ub7~krqWXvcl97^~YUx+Hh8b=?d%(wy_S?s~HMwR^| zg)Kgjw|ty9{<-lgFEoq%oHU^8+O;d&r#|_KNW_=%-KUoDmCRBKRQER22lyEa=MFc6hTwN}6_I)EHmsRiv9FQkBe@P$R|w%EZeq2aAxLGFYCHSt1t zQ$A)fv{PSbN8#?nvKzq0Y7g9eQ+F&0X$`m-;O9tQ1TqfCKH7t+G2TS)zzBT-V27cc54edFY`P%Fksxi_WmApP6CqOv-}0}W zBLFYx*2@Q&X$%}SVjwap@itE>2TIt!p7^elyzhPQyEzHUP9_3IN4J;EWtQaj{VQgC(XJDrR zC0Qt+#Q^qO-0`U)dr%#GzT%2XHTH)e+`$&OLk!2Ltg?fzSb@4M3rW;KvyE@ZygL-B zKKdfOy+8tjxR57}UV9>RKjg#f2XQwt2h$C@7oQQe0SgB|q#%HiT~PG!1*q2UUMclh zO!{It>LYpNmU4jLWQ~8rTdhFqJ9DsUANs0uY(ugRZ<+Pc0;r);WjxAu@T={qJ>pni z1>z?isz=3*Hu&(#w z21>DrB@DK{_JhzJe{j$aa8~sG0PuzGi3h|5;NV?LW&pYBX{sIg%DbSEAl+&VShS(< z@ES(-0{GB%iG%p^VcRvEvY1e(0=ASu#LzODEY#mq{#@wgmtWrgm;cuPV*BK$KG{3; z2?H0__<#BT;lK8;Z-0WvqMv<6d(}w3dV9sSwMDmETEUoU*t($-^zI{i%h2eyie@`Uled5AKMKZevZFQnBe4h{d6ki zu!6%b^set6U;OLjBm;k4Y%S-cA@Cb@U8Q z41ChmXbvol+gtR?xg!BJ9Z6Ff4f-4y8}*6M9=Ih9eK$ru#dQ;o`mxFW=9)1wqB|`W z>KRmf|3pxpz_P!xH{c|!)x(Zk6B8g_-N!Yk1k|9i3F4Sn9&rixajy+D_8sbbe=Ob| zNms4zS~^^5<#kU4NTSZR1C!*yE(L5hEW+iLf~|Z{;wZZb3dy0sOL<1ynlJ(lj|>y8A$wjEb%tL;@@9n&t$$fJNVa-!VWHaVkL zT)=iPM&XxBJ@j+OPIO?#MHq%umTiD6%DB_|VopGR`?r7Fmr+5dor{k}ju%6{``z!^ z?!W&&e`C}x<7Huo9iWdnw&V4|{#~|!l&QkcSh14tjT_gt$G-VkY@Ut%^R|a^#6i=8 z54_o(I((Qp6C8N^k%?@~C(nl+{nsL_KD&zj|Z49H0H&Uu4TaE-BUU z;5k>h`CyDI>#%VE{on%+`cjt)wp|=F?_(i4xtm%|RbIXDcE=2Kn;d!N8m|S5PjB#3 z2yVw$s}P)Rq0U^SoTLt~innb5((KR=xLfS9v6@ZfcmHN?EpS|cO5*Ov8e`g~`Khcn zur*o7uQg8M1LlJ+>ryzy;K~UT2X&OAH+=`K?I<8$wY0x&BIcvGeoaz!@TH)N5?FwI zl@|=>$gVm%Ym3V0)Lswb_k)7qmQT0MQx)RC>_N;osqz52q1Bq$Y+Mg_-s3nH-*$C8 zcmXF=aLg5K!UV546;=cJvP}+pxu(vH@ga-HhL1#|cN~IVAC_OyV|Y3~8n2`q_Kan9 zBF6_|Km+v?N-z9XFBs5W>#(1B&0nmEoc7Aq7wn<`Fa4#zynXlgzq8$W=k1|zk{mgG zEH{zhX%VXtb>B@zf6@Rl@7@H9oPNiO&ex|gSwIdRij&y-*zSrA#9C>Y^@w~0B+2zO zMMu-Ev0+~0C;TLZ7c8qIBOJ=8Xxj=^!QNrUCOAG}S#{%$y=nW-r;C(%1p4N7sVDV+dW)>a$F(H~26_XCjUcQi$aR zj!MuRb6}G4Mceu*OaaV-;Z%pF`^(XKCRd$ZKtZF{$Yl8=R@Ct?}$v9v7EC0#{1Cyd$H8zOU^|Q z@)b_>I0xBhquY2aUsoN-ymG!wea)K%u#3ZIv=-Wi87KK5jy>pbwZ8ODj3-qoC-Z3o zdX`q>P+IW|z;|4#&URCvP8?EOYZBt*X}5nbMTNV+p<1IU#%c7gP0fm5Acy`8oB80v zHzHz9!`preC%Og)R5$4)ESpPihvmz@f1y&}?Q8g#`Xe#mmg)&0MoW|&ee1@VK1hdJ z+JZxWz5%ZX6T=Q_p#KX-fx!}7g1UY?!@_sst{uHH2M?X_$RpxW9<@~9MfR|;SYYoz z6RRDkpmh>b9qyIi@%WiyX~~%|pn|IuJjLCVcLpBr4Zgm@Tb#w=^{Tpj!TY%N@^8WN zA-F6;*REglitZ`?`!q(lBZ`f}&FxGM4$hxB7j|~aISIb+K2M0;Iq6#`-SzDBNUL4? znv6DefX{D4z$WIb4?RG{_2h`**NUTR@ReMt;h9*t)58Y5Y~x>W!>)=JP+K2qPi;kq zPbp40r2Z$|ZCTV`@rpJ(1pUU>wEeET?%3|S;|^c+0q9Ej8Gx3>)}!t`@sqa4FX}_H zFLf#i(sEPePupe{)&(BxfyOcK|Li6Oxh1d2gi&A}Ka^Wc3uY#CSyl;z17Y1 z_n8np)J<&nF+n-3_;~NV_ilHlk1H9yDY?U!H`s|!557CDrG=MmO|l_+)k1Fp#|LT5 z8FE_A zZT&CoW4}qe&)P=6*rHOlE^hT(^}^mR9l6!N&a3uW9f6-RoAjAw@YzI$Vl~WWr=zB_ z(x!QZkxYhUM_^*NmqxA?smxv-md=I=7;q6H?^S!YwF7mXW zSTK(nqtQaYs$z8!5OeSlFN$bk&CBU)KFG)WtR3ghU+@vD|2NP6>FQP2ZZ4h?2T~8_;E6sC$gx3=EasGNA06f| z^i>W%<<_!Id5sT%_QT{Rx9lu<^#8^+ zPJXkmkIkz&ws^>y_}O^U$zu|35)dVJwRh8i*||QiZxrgBWET3#Bag* z*k`*?q5g+P9Flp`8ytOp+BkEQL20;$fA|8-A7d1n;h}%5v(Z?JtUJl=XX+y(UjS5a zho}e8n~ZktyaYtpJ3eWZ;ikNlrtCby_l(mhp=Wpm{XOq~x9_vyA}u#Iu5(<6i2waF z$vD)n>ITry&z`cc&If&1GX{|0Pv+coUR8p9{dI1du-`tF^))dq#HUr<3&e^l^`s7h zl!>c**TJ*YhC~ob0P6lU;BeP`-zT0FvSAB z06BQ=4u0&x%g?b~H%5%Up?%oUj`GX*TYZaHKvu;E+(AcRmC3{Baa@YE zeIOk}Sx4^>U&DJsXz?UZ+U-xDQ}b9jg~lb|@lxq4XY`ObKIJ@xKBH5-Xvy48;)4!y zG-FGhOV=B40#0?&rZ@w5;?#JBW&lOC!*)7_q`?h31D@$U0McGf7CR>D_6-{*#NeFN z*s46DhfagHbuk?5G87iwtX*EWiig{wpk7ffJ`~GMB{gMQb+IO=?f^xe#Q+~uU;aYL z0l_OTU-sok;J6EXBMYapqlCL_ymtaPd*=Lh|9x*VMyoAqO2Ip%+<_C@nT?(?)dFRF zFho?~3rrjKc)&a5W(S|!4st5R!Q-L>E_}v|k9{F>*JGYkTkwJF0>m3ec~sZG7l@te zpl#cB>Czop=(3ZK&a0QNZkMyu=}W`X3Yx*eV3b_rARw~dK}kb#7koGyS0RX_{s44G zp85rz62387JV2`!7)Pu)`y#1#=Yj56j9KLPaMH_LR=@VOug+q%+J`)LZss8Ins;R1 zoJ0(a5s96^q}r@s=57N)>v4y_bzWS>8(Xo(g_B3W{*CR0mtNkk-8}q#20QCde&Q3` znX_m0;U>Rz(yxv&he)!PaIV8Y6pIdae$Y@ylb_B%YmhisaiaGwfEnK_AQaAZ4RA7jTz z`&tL2L-S-}>ZMQvhp*T;=rKO9;0SKQ2_EF|S`M;WE61kw0CdIzdGydW^*{p<3C;@^ z@Bl+xF)x%ZPF>?C6#1G~8;YmTDII!d*}x0e)+96fh^_mDAdo?bHkuvVBf&k&G&%eM z`*O+B-?QdOr~guAX7jt?U;dSUy#4&o|BdaQyYBJn65!BB)+TY0E8_qfIy(JfZVEV- z0@|z@b56#s#E;{cwhe)47qHXuee74qkz9pZ4qh^t$n+y6eDzC?Bl*gb7OoP9eE5(2 zqPX`h=v`gyaBd1-e~1qO(s2NR_8@{^y~E?qcpTv-!%KL+ci7gmmd+Inw?(pBVs$75VLs@4lf zB>I$?a3>g&`onwe#&utMw%V!Al(~MnA1@DR(P}pFw=tcZB4)`c?r}sP<0{4IJB&;4 zl;eAd?R!1n<>V!US9G>~sf^wF5Vo|yZ`2<&q z#ow)dScF~}EkUQ0ug6-G41D;@4X*L8wm0Bb$Vo7v>VR`lW^tX+PYRO-PXIJ%P+ZYM{4jmk)TkIzbTX#XnSpQ z8H#1mKonGDk>3ZEx@d2xVe=rnV)L7ho>*M=QKyjfp*fE|@diMKEC0KA=UsR8@zLQS z@v;DZmwD<;e2hHcqRC=E_LshF23N-7x^Scvpnn3hqd>SjM^r5Ng^x_iE8a`~aNtyo ze24|jn*eK?%~6_+$9n)|9UntFf1Wpv(%-MT)8{Iy`cq$zCBoVE^k4xy%Qt9zpxIKC zl4x%jm#;`jK#gOx{Cycj?7%A@fPxhpRL5WREOc`Em4j0rJ$pPSjo#FX2 zXje{xKlI@b`5(}{97~7}Xc)M7@nUg7+PC^#Ss8U2`p5)$jQI5FoakhnedQ}(iSCQ~ zf=^sXxc8pBxA*s`2QA6zcFJ*poq61+ z?cPjuym$W4A6;$%nh)6 z8%D1&T&lyc>jh6?MmjMjpwlrixTgyg0FoB#9FWiBzasW8`2iz_nq<50C<}gp) zuO@*D*FjN~=xcJHO-b?M`3u{(e((3TpZ@8e$=bs2gHO$xQ9e>Xz-*m+-Os34wrnUm zc0g#^I&?5V{h3M%ZAaUnj=;hJSVm^)YzhqT;Xr=yyZROu8&Hp$&>ACChv`6TV%rZ& zmOo;T%dBzm1nh?-a?OU1{4DzjdEoDRG1%|D@cgsl|BwIs|HJm~_q^8&tE@%P(Mf-> zZgbIr!NIY@h4bgP|LuSHA8zMPpY^4iTo46Z!|FzezJPeB2SB=5Yc+~E>a-*DA&Dx?ih-|= z+AZs@qY6S68CZM}0-CA(vZ>7IUA+5z39kJaHpfW$YAfYEzThj$Pd9xeI~1~ z0r0!O!&_K5676dBP&g=D<5|&>*QXtS-~|r#BfrAhmUpX}Y?e9J1?%$}ta6QGF~(Dh z1UV%I30~ar0_!G#oE3bHzi+?+vVO0@K#&sbn*@9X)#y298^a)tYde)bB)C1W;x1J1 z6j>FIc*AC0xz0G{nVsgaVlWkK+u4I(oGvn}r^%cgdnFl_;SFv$cW@BkYn*ZU3Pa^t zWUHHY;2-~mwkG0!;0h=pck^jW7es#V^GeXcv!I)=-+?9u*~#60`|U1>+)ZPL!_JNb z-E}Lz9DXl(l<>hK8>-j_6+OC#M@N2Agizvv7c@FV({HgIqWuD9+5@ZuP*bVm-HJkWdf9xBNd8ZjXC&m1>``nrI8-KIp z_&n^;uI0eXtK2E0(>M0w9etL8d;Qu?fAf7eeavkU{MV)p(H~;dRuYH$)bRr!8|rNX z?OS+k2B|-Qa7n4U#iCf_({x%wh0DuY_Uxn;aw13$Ub4B5s)G(Pl_&V zQ5To8`y-h1EuOijhLCxB2-$4l-+$V_ zLvmgAc4oMk=d_J38c-!T?S^mzy=bkkwoSg!v&OBtTK-TVb|c7_kMRv0=PT`WNh1p_ zMeI&hx>Ry}VXV%eZat+{S1)C%y&%xq*kx3Q*9&?3dIQZOT;*3!V|(gMN(qSC!i z_r&{%chPqn(pu>@^TV9FmZIaNL-scT0z43kgsFqDl&L!a&^Sq+)vL#Pr**K=uVBWm zUL;m@F@3|`*xNG?-u2FR`Uv`R&*QYIs7C0x>~UM#ii!9DSBDJRgG)aG96zpOKz3F% zOW%^8Xa@TTDABD&bi$Jl@f>W>jfqfH0pa6Zr7$qBhw+$4$6M)|TU+I1Tf1WCII$Od zz{?b11T_A9O~fmXcfX;SS{+aJaT0t$iBp8R{RG2)x0p3Ipl_=$!b{Q=b?Fk=me+d9 z@D6TJLu)@yZD8c-gA?eH;yd{I0BUJowCc6Yny|;2dW*Ym^)g~4SzolnjfV0tiw>4r zUz7rURJ!=+>PSqHW6vV3zX2y95lmo=JOLta5@jzmaLvFcpwyuUI>E(=Q|<`XfNdp7 zmF0)mlT0SZZmTwcl{?^W_Seo0zpCYaR{f4D53bIAoK_1*ml3d3ER>ml@t0(yBH!E`to7v=doON5Y*VI zb3%B}z4vYpKJ>usm`}Ft;CJ+(H_6}832>IbQOu4-;gpeEXUPd}jgIK(%PQ3Z0kvRO#?eIXL^5wpi`~0q&#a z0N5HG+8LT<)U>Y_npmW9t8<`i$39)J_nc!D~>WH8MeUQx2cng---FAJhoOmiMyJXEn2qXhUlE>$d#C~9;L9I zK6`pQd*QqX?)nb@B%UVW!Y&u{ct6E|`CtC^?bm+&*S0(ExHIMx!zlLelIFv3TWvxf z{cFsjnQ~A5sf$T?(Icy4vQXOce?fKot&DAN42(lkb%ig9BGC6ePzc_BqgW60Sxj@~ z17s`ip7?1iu;)p%hxUUDFMYM>-7d`|Gq6r@Y&+{?jM|3i<7Yu!Fx~&|E+^*`}vE&cfo?e3jp|BpFkO_NheJGnD?E&Bgw|I)+ia0i6pd4O^1E%{)VJ^-ts)&7g>H5*VN-zrh>WYU3Lwbx~RU ztS{8fgR?;`>jOX*68*PuwN$9=A0A$hADp@ut&R!KTNaw&u3WyH{ph>4d+)#Bi%AI5 zkNg{hW0gc3Y2MCdmWH*$d zArA#;-EWN?0rl!`78&$Z;iT|Pu{yC452^1g-M=d@KO+O(>`NsJyS%)u?+_H&9xtY_ z)2he+p(IBh{WRFt~hW%J-$mJ_uzRK&5B>-G`Pxu|ET}7*l z4CyIbOPLXE`w zF|*?&fM|5!n+;H91ow*!Z@@8lTzgo&+6fLWJAuF!w?N(rcDmG$fhOSL1=ra$9K>Gn z3{KHUyj_K>6G!9=HDtKhc?0?-e|=kni6n0lkLfPZC-tHQAKLk?s#zU{8ubJjUUZT` zW>s75UECCwUKTfg&%uxSIl=P)1nc@HcSL)Y{@l5*#wD%z1IIPx#PlVzpZGio>CqUOY zdCG@&KKS69{hia5Ygcm+aLp6R4}I`M*~y=C$J4&9zWNZbFNl3@XuO4jY-|SSP9;9m z=J2&E8>e!FN?9FAp&NtsaU4;nWsDDGhnFupt#fBSKIg#n_rLx7J`R002a)j9_Z}Ev z039FydJaq)Y-Z*fKG1 z5nfW|!M8u6dl$_H6eVL4-ikCIx~#J;y1c^J#m|l>tC6P-sqFq_LjipzqrxyPfD74p zE(F^;650**x6V4i*p||yoyv+qap;|^#GrcMW50$5qkvcn zhu9Kls0+|>0#P77wtdl%TWv@hpO#*qyy3tS&TNX8vl_s8;29k$lga_KqGtMN@lYon z7==Xx&{y)b`-u0}x;`ygHrC6~-`p*&!y7|j)XX=y8Lj;)+Jbx|-Z8T?NbAAqfMbvF zMw=%<<@IDN>+p*&yofOs;uAdN{N>S|7cXqT@+-fx{msAix3@d*yjwg^mYmB8*cz)V zK3Ycyd1}s~nkt_9|DU}-4Z1B$@A|-1`6VgFUDIksV6 zp8zfzuoscn|5o?DOzyr$5#|wa3$z5JvIK=A$|@eo@*^{pksyJER1Hf2mBp;sGFM;8 z1*uro;aB$!e!!3uWERU8o_lWlhTr{rwr}~iZ{2R*y5)I*7rEiC%Jx&wA^3}=+y2O; zOF{aaudeX#3f~_2Yq`MYqMH5J^*T2E6glZ!_E|3I{ZHcP#T(bFl=WR(Knu*eGe>P& zWKp(1g=yD*!v}yyO5OD;Bhoce-c*Ap1Al&ABL~CcY#w~$wX6>flxqbApn8=@OiXq5d?>uT?zXRblYH8w zeXNdv=isWUro}5&p5Q$93=VN9`Y)Sw;=%bxdF%gSt;4rudmBa;&{jBziKQWhH=2+X zvBz-u7Po3g#{$R60F*_o4{gH^sq`EG{K1C`)*e>+8Y=6A%jqWv<{i1G`ld=(9AAeA!S#>O`y#>*E-KZ7ITlvz_@A$ezy)2ZZw@Ym zGEfJq;5F@C{2p<=IMofX7_$l11|VmXsK~o0tyJg&P!`4x7gJogv9Vvgcxn6MFaDzK z-S2+)_Re>_bNliy|8jr5m>3=GtQ_fM`z`wk$&pWO*0SH2p+XG&R0h^mUkito6qa=P zfgK}n;}hI0^3;i^7w)P5)KC9ZA9GHbyZdV49ln!X?7!iur?+RGdB$G~w=e8ZE*yIj z$3jKoyI%H_il&Th%wso+3*6g$w>rFhhv?Tn_Ob1`=U?#qyD-5A{eAEKjP3H}tI^q; zCj}T<)(<>IX-b?NFJJ2lbaeO-5OcvTQaJAqHyk9PU!ei59uqFpKK$1G2-L5l|)&fe@$@vf_<_@_m;uu~}^)U*$qM%bN`O zft^desEXu_kEORzoG)p^JLMi4tKvkS0x;4j?RtkldE2l6eEA!5QThg)YVX(rSAP#Q zKY;|*YAVI$}0|yOIa39KU>;i zR0PI@#kv}kY}WzpSi#4{tD^+pYz$YNXjA4r0}<|513I;Y`WhBZ}N>2GAPb@TR}?Kgk*S8reS zRljMwdE-X)FTQByiJ`M+xbU7Ibb^+b!zLWE0r(KaM7IDU^~FL-9{I>Qmb$MWpv0AT z$qK1R4roVWN;t7Qg05H+H8}13FNN_nr6vAv)54hNYXLq9mAGR1{U7*%|Lg&%hogI7 zaJ#>wwGLBo-Yv4xPKCPd0*OQ57z&YRobbbv@TegL&W-ScK3_Ig-yDa-HtvXUq|BP& zO$hO796mSzy-;62JZhbBm0Ie(@m=Q11L&5Q8wRX5;?nQ%4o_t|7BnBgPAm8}cu{2_ zJG22nqAwXanoT>jms(7YXCP%d;26@_f<_H2^5v}tFr#7dE{G!QOPPufygwZ@G^7U78-}%mWZcje>({Gi@VhoK$HvJf#zNS~HZ?cEW_MIyE&zkXUdzcbL6*(X zyPi8Ua;Xpua7p_@6{rq2g&@F#To;o8^$@>i%KClMX&0Y}pJYMj2f#l2*M0W({`Y^* z_Q)ew=faThtDyzyo+MxwE5zY=9Q3gmy)m&Qz`HOxMQFQRoS~sJG&`xhvr^?fbaA2D zr?pChL@NNfx;ui4yLkTGcI)Pi?N@%~SGIHK>4zwgj1QdX@JatG+h=~}XZpieexk=G z`Rsb3>$5p1PCmJN9~6BIQozsHlMr-t(mGUdgW+fX_0J+8CoyN!<9|Cp_j5nscbL$F zA3n-ob7)lO*)#p#FY@Fk>7N%q`GO~5-5z?96=E)5(|+A%oWnnQLg&*CK7FVkZI3rU zQonfd!uFQ8yd@X!jN5oVCui!F69_Kgm=6s#i=rX2(M#QnpyBAasQ;BhZ&H-3zAI~V zn+6Ax$(6bo`eAG#)^ULTgU{j;UvhY*C)N9c%NPpiuOu%d&qPRPVl{XrTURG-KnL|cLNA|vRGjiT);0+|?P~j1 z@-f_i(y4pG#yGJ-NfR%9Kz^qUfUBhdeCQn6B*ruxj45uUuqHF^=m$>r!Qw0L_EA(M z9+U-eNzBQ{HTa1+Kp#!9cmY4AIJR^vRnWL!^}#b9Qx-?RL!b8Ilzxmn$xp>d%NCys z46buHJoG31l)B=!hg1=B4~YgDYq7jAXKwqQet5FS+&l5H%Jmfod6eWw2`_9nZd~8K z|3CeK?YZZk->zhxVr1e!U*q6Hx);UeZ+}~|j4JZ3O5xLd@X%82_~&Grep5kpB=zqG zK^BZ5b^CeD;A-6!R-ALhkT{@2AJ0LvlE7F!^)L9nZ-cW<;dkB?2k2W1$`D-g9nadH z@{ws_^*cI`{q?)M+#t-$ah&AuT_mozZ{19voZ0^PAOD{1;j34+8`rP{&>eo936+4=KhG<}qK%p$ESE5B|aJkw+ijZr!>;>%xFPndgq5D4p0sVsFB) zzQ9En?VYyneM4;VDaBLmB%#+B()YwPT(E?{C+x&4_Q|8aYY)DJ4<72OoC^r4sc9?+ zVhsY{WPl)g&+XrZ__qP#WUvnZv25o>oJpKO@g(1qPd>iA<*je^JT08*JKE3~RVt9e zno~g4g@-wrcsd@L1`g6a+U9(H2~Em}U%m8obOgJ-nmrkI{(!LSb?C_&M}YW}u!Zl? zz%0Q(2=vG3H0o-ryQv-%QVWUC#}=F&+T!qRtKFOC{A z)dh4vT2LAuQ(oDL-4(2&V+3@^Cu;gKJlWaZ+O{$UuV z@r$%JNsmBmxkyDm!m#&54w-V)FYfko@ zg1!d)N`PxyR5JlUagtdI_Dbwxlf=RiB5~~Zq`=`T$lw&@A|(DKRnhb>6KMSNld9oG zVSfOj{i|=G*jfvr0mh?c!skidY?`onvKjfiIU(bbXg)pFM2=n5+XnlbM9qGnkFZTq z591Gg18>I*xGF2J(TYEfAu{t=sk`gJCxv-WU)FvQHP)uB6Qz{xgf8(M5C}pV;z(Sf6sB zk8#3@>$&r1x94AYe*4Lv`pJ|psu5+c+`YHG>mBdf-tfjZ`l&G|)A}^AupPLcIl1mS zQzy-IR2ytzQCNR*bQs#m=75)=jWf08L%8V}_%O=^U0WYpn#%whV z47~wI2OJI}>#jG0^Ta~gH6HnN1J-Pu|GZ?fEc#j zu4C#2&o_$t0&Fky4sjWZuUzoz9{l1B)H^Q9C=oXif$D znZ-p-8yE{9mN>2_u14j&oH5?&277MiQgxfc{<+@-Pd9m z0<0ml_y_;SU*G<}|I`1tU3r9GuFpxg0SiwI%bP^5pD2_*5Hh&7xAW0)74C;}=HCA&I4K^5yaHWs+&@IKlz;5F0wX;@EsaP$WV;YkHw+eG}D#Napr){xcAS~~z}WE{uF zusWpGA`_RYWd_itbHMPHl?uEagIyx2{w z=zDHP;`T|_(Zfi|5gzsePDN;U$`2)RL;1b$dH44FzUdp>ONb-02G@v9Z)h?O`h!o( z;r95Rf@R~s5zUAy?y@?LRbICB%|-S2+S_Vm+F*Iwvr?-uk4B<&T! z!MtPOz(?uTSJy8=Ggi@3dE)I?qVnqb4p`<8I>JYP7(e#Tl<_w@^cl^ZU&E-n`qFdX z&R=b(4~TcyYINJusiOtIlI+_cg6FF!%DT4zvpy`kZso zwq64;D%DKUr^qOJok07RUsWQHX0er5CG$$%^H|RRWeN>`9Kv=RJiI{x=4i+o-3=s6%NBA|b41e}LRQU~8!s?nho2S@YoNw^et1Ol2Rpj8Vr- zLA;f$6;ZnI0AsE{ZU|5OOqj!E)%zAYdzb{6Od6AkSb1!9+c_*Wm_f1V&a$3YN8x-e!u# zFBhfI&@XCq!Bl-=)_+ix$*|93qk-`hCm3Q^YCvA{B@tS1s#AJ#GI>F&F;y0j(L@^u^bub1E$?w5 zGc~p+M~^ypfh#9E`^eYCUs%F`&UKO78AkqC=BRBR;^$b?MrC^v#z|u@wgY65^^+uZ z9FjK~)X&0w@Tg-TwXh*WpZ)8f{aF`wZg`OJn(uGJ$M>F}e)m-@;)V!| z5}St08$!`Z-SQsmaA(Y%%(xL?ImeIQoZo)xr+#|7eVgx{mmd!9Sij>P@4!K0ho7j^ za^epsI=it(ulYmUxwPR|e&r*62g$J!UgMzZ#u7!~utQzGnhqRzX%jqr;_>7YPxLW< z#yd@Yg|ZR3F|g9paNyO=@3vEZZJn^inTw{F(A_4K((< zXxcC9^uIc$uc7eT>ro1?@Bm+x7Qeud?tWB$#S#YxtK4dD$9PqV8$3u#$aj6MTKolH ztt)<8Kq*!4j|u* z@l?cVF-5CXlA6Jj92?WOb#Kb1mMN*NDm#xT(@w_HveE)*~dsqq`(rE|%^vp zLdI^(!xJ0NKll9hTfXLNwr~5kZ`p3%$(kD*d}o*b;`bK_92f5A&i2O^xjE5K<%xCd z>oa@F$@Eo!gM-JSzwUz{+}{7$zizwn^2^$$5%i9+;SPPky`V#4_lqXkE>gw77PtBV z2*0T88D;Oj(h&dx#mO6pqyp61YW!Cmca8&VKyHsM1>%FToGO5Q0bNrBR{zw7#WE{g zyVUKM1u4@1egYr-y?ZCydvX!{@Rgju1qb+aTlTXB_QjDN&;1-i6Su%_Av{YDOvv)Y zMx?^S9OY|8=iNWKVMK%Y7m7YDr<6Ej5X7!GHf4vl{17wnU_an59QG3s+7bJz9GGN(gqO`qv3TfO;y;n(NnqzAg>=s%HnBZ6Ggh z>D~43e86E47oD;OQ(0!|c)x5NkHr>g_&v@uX020vfOKoF=LlVC1`1TlgGRr@pucK$lrY^>| z1Y?NtGi@dx|0|0KzBJClG=|uBV+$=IpdI|Z)3s~Ywhw>!!~H%t`or(vKC$SeZ9Ibb z-uJ#Y0*p`YoHjmuhjx7m>q$*sY^+zWUR5_Q-r#YIv4K8};2}R`!w;zZ)KC7jCrvWP z264Xn@Wb2tKJzns(HtAtwP(1CGX2hpknL8xO_cU?Kl?L>4L&wkn^>!T1R6~%$-BnTq8t1(Z+XV5V-$HvLg$0}r{AINHz};+12JQaE+}sSo6rzE#xGDI z##=Rq@4&mP9eDRzIhH(rSQR@ti8dVYJj!I7l0fPIu!7UwR;$+>zU1;-Ei#EYGO7c? zskd4~y>DpvA+Czr-9=y)>@2)IVAN&a`P!0 z9*wOJul58wvR(uaFRom^d~y4y|NNhA|EIt8xBB;dvFm=56DxkG5Z9=4lFqLa*Pp7e zS?D2)-PPVS)HeAfOU$wMXmt z8lYboUr;lF=yQ%u8;)T2Jp|o4%Hc1lWV|S7i&va+e@mS`)RdTh;@M}n&;P>D-~P;> z{nOgu#|vqzYrHaOOO9?(c{u}STrhM=cW&KQA2&OBvWkmmZh~G+-+sq;eA{*=d(pj& z1tEHrjUau@1*|7{_!=itvJKpjpbUvNQud~cG-~w+#~T6;#TP+&>d9iserY`j6_Zk* z7_NEX5!|qVmt}b6RtJT`s3=R)G68{%^5SW|I@{kCMqSpA#HO!4nMM6GKI47EPof{g zUjrhY7gZp@S2&EPMW*UHw`z$sH_UrekUl-*xd9##GA@L9GJt-izlezt`}m+6J5Z_b zLo1GrNyYIu2SBZxkI7XD=;)t(1228jW3IkZr{dDGvu?&*csD8$XRvnxZKT>c=?OcE0SO*l@`)x3Ih$aEP72;$Y3Ekw(lxT?i#J7a z3%>w+!0-y;aS~APBqG%gbO2oaZ4RpP-5cXCO|n@0jN*e{7Qi(E1D@c8=hcU}z!{m* zjSS>hUp?7w`=5W^yinO<;i-`3fbWzcx6fIALDGbbbKR{>8CCVeT6XuOUA(X(%^TS>E;^*Q)y2l}W3fi{XB!y8Hw2zcwH-9v<;iJixoCi$3ps|Jj5UwFiP96gC7T)UC0Z;#duZBq(^908AO<7FCg&27fj6%I1BL^Q~p&o?eWA(3k zs3ay7S*k`3Qu`l(NDR6@biIU!ujXX-Wi8tOAtAz-FJIX{^x5rFW=}bDh8vW8 zs`JoxOkJAL;r z4&Ky&kb~_fw{iG1uzU^deHO5PXO1bB{s4=Y^r`3rs4$X5gJbW4?W|N%%3{Yy+L`|CE8$`_&i(uwUMu zb5At~&I|9)`6X@h2HNN!O#(5oO`(fNKfE>EIFK)?;T`huF2L>(0C>%<*#@r>0*(2> ze{sy)(N`N|Yr(&vyh_-n#f#MaDRE)0i|jAKPvkS!_}k7D+_QYgubk~VE{@vqI_z-9 z6Y@RybdaGOR1O4=@*cqCQ}$$yI&2Jt;7@h<@Ul6bVQ`$%k?hFsJ~B17j!?8v{v-X0 zMCaPHmjL87xXW6-OO64u>l0L5xg2^T2XE}AIATt4Dpoy2hKrr7Xg6-&^iw;3ga{H- zBf>0(Y+6q}^;8F@ClFoiSnbZ9t1XT_LC$a=JLqqkvgl4QF#0NmTJj=O0Gpy=VG}GD zY~Hb&206Ks$Q!|ynN%sM&-F2jPA_ST!}>DQ6RGKg5b`pAiKF$z>_0!NvI5-GCo1)g&estO#AFxea?brBjHUi zzVhn!i@)?so=mW0Bf2(xfL{mahtc?Sm%kVSumcAwEJv*6%Hv!8i)~W+ogv5L#OKfV zFE!eyXSQGdQwGV2A}91}8#j!X)1Te(96f za?*=UPNd>d@a?k#K0;RqwCEi|0IzuDC@+a@^!NSYv&Wx!(oZXx=M%bc_2@}^N`3+& zsQ74}b@btdx}hsfJA#K-Kd8eGJzSBeRt5#AOnw@)r0juraTXsyZL-6Od_ndlv*Seu zU3}}X)lYnqcgV2WF6GlsV}U%>l$ToJwB8n3Gmb&TzI)5F)fF=K}M zywFF!bm1m?mKzkrQKyQl!@B@l<6oTe$P7ws##Z%~hBMZkhxidbYz2ox*Yo7-#suIj z!e5z_VsoUecP-A!iYR)(4KMZm7k-&1L30QSvfuONlfL>yI=fxCaLM%x`{&P{_bU&7 z`7eL}_VJH@!bd&*Kl8{yR(wz)XD%1EtDU<$>DJ94D*vs9hbOdfL7E;5e401q&{zZ6r?But1sRFFei*NjpF~EhXy? zloy?LKvD+65u-jxWW9T3yLa!d=Voty%QM>ve{+Sb`#AAha_BpF;Fw&28vJUT?FF;g z!9iblY>=bq-dCuV?8iLCHMVLG*e6(^W3tWZJOwy5&dpbImy2eKPCqi{s3L;j4&gGQ zX4D4CxAt#u1X5?tfXUnOufZim49J(?=nca5mTwQ8<>05@eox&tfMnN4Uvbm{y)uqO zHUR4pl)b!u>Ti+x*Z2X5Yhz?#SuwP}bO%7yp8|L_EmU~-qRh#)l|-5N%{tb#oUvlH za8zkqtJ+T|6O-;$LrZ*!3QYb!0xYR{Ge9hr-Yi3JXF^Aly(q)$@F28zCRl|PsZ|fy ziGz3WlxAm7&#y_+PfjfcW|G(;fn7FucpNM#1jj-RbO7!O(5&pfAqL#ck~6S7IN;Di z<=K$J(ZO3hbzhh{peAoYRhBriP#()4Xlw4GfV=Gcf9&<^*E}&nrzhxPV3F`{G9Zh#+lz$Vc$Xh(OFSK@$sQP|LvyOaez<+X9Tr7yNW%(Ffl?PogR=HueyN zH@Kd_FJ9yaH+J!LN_!kC3U*Nf6mv!@CI=o5{N#(D++KM8c~3x8omdkFWVtw{Z{Pm* zcR1#&kDM_PCi&^JDdb&i_(r)k`jr3Rl`kl;jH7#Z?`;3`|NK9d&WT3ifITjjKmF4` zE%ER7k8QUm9@@_F$aYpnV+lI4Jz2)ax$T!e^r2j=r(aUvr$P7_r#z0e?piu-NwMd+ z!2PJ?aY_U`RwBcr*;gO&SFw>J1dYSw*cw>lrxke1x8q><1?-(105e$UJEi!__yRy6 ztNrqw(p`ar{h?76lfq)(rIt)y(w2<#4_fNG9<@*qcdWOifn@}cRmD?3@Y)XXtG*wO z_?Tra%~-edJa<~-j&~F#n!%j+Db}wAM*h7glr-3OH08g zQ|FNMS6u7j@oUCTrE1@L@WmbQLkggG_1TzM^;DLQ(@@;HXaKZ8OTPoEbJ`I3-QOi| zl>>F=OLKYfY4Wvn>4P}R^Z_U)D1DO(Z3X9{7iRS}b;6LW^rRfTV9ATMhMQJ??Zzij z`WGxb!SX|Y^KWeb>R@h$CQ*K^^`%h+V*rG zl5z^lJ29jlMB8=%>fS^ti%{Dg-&ImO>Kfxqjc5w;f*f7}9Pu5lkr54FijcbI1*u-} z<>faIdNG_j%#^4ncEk;H#-59+le^osmtNZbz;}M<_N8C^CEJbbH=_fC)hVD~)zp); zMXh`Q7u0-xiho(aH_&=ufWkLp==PmE+o!$j)3$H;hHuzje)+m>P*Zf0tZSAF7fq+g zI4CTiz_))$st<4|U2s08uKeO94G;38Z_j}$pGvu99XWjn!k%zEF8>ZP|4x9KDVj$o zV`{v19@Q4H!$!Z#^zL_m`gZB!#l)(gtPuzH%#OVkzsA#k;v%_7!QzUIz}OI}AKdz) z?}}#}(7%U1a9R)uhW)m=xWisJ zcx`k|S!Fm5FtydDNMlThuCaOQ7&)UjdR~XqU{5!26QPNe@doE85Y;|Wq6qI~(p!yn%IOkrPl!wK zkMyp`B9QN(JPdR?2{KsmbR4`X?eb>Dv!tt|$b#ypzIe4+t=8k0dco%{{(%LodRqqA z+_OD0#jK;DdZAVP#TQ=;p}PE}a8$B^0&HeZNToZu5bj;@>f%UR-mXQZwxTmx&(lUe z^~KA<+#r@$9UNKo5lIfdR+d$zgms73yZ$W-Yr(Ux-Bg3ghQWn#H^e5|)y<{x=}GZe zA*SScLDRZ)Xy_-0x3bXM-h+Se+J1nX7z-lGcgk#_v;k}W9X9!$M#PV0%L2(qjzBa08MH5CQ=Mw8;<(d?QLv%!WCXyNrzaX z4Uz|zUo$UqfRnWm%5ueg=}mdi6>J+wb~aU%$O{JzizvJ{d#1&F0a2{@@An99QG$6dOSZv?Z9e&Rp)R-lV}}c z3Zv$z5Pe;Lc3$}l$Fa3pyvV`Fw_f1WcKV_7Vu@hkVCA%~9io&mTGQxEp7w!ry|MAh zlUj5o+P>fmKEL9KkaBPz8y(0@!Q+}M*c(h)M!xv^emutMH6esE-t=bd^(mgEpidL< z{qgxN6~}0GI2M4&FTLXOCLV-L-{OR^OxZAo0qr9am^mI~$3qJ6Azw-gv0)&Q3`V__ zidQfCp<_#2Xc>FRtD{z%fvB-m^9uiJ&$4Ok91yK5jcUed3i8wm>*zpb@rkXx(5N@Z zJ=#@!>;r=v`P$Blw#dqH@JmSm-sLx-Jt1{{A{Gl(znpdl6#;yh;wmUKZ4;4N#sy8r zhlO2hljlJ>KfqfnNs>6nn{tfDu(ccp0=?_NfE-#B18Nm*YE+P?)Gn4{cTm+5sN_iK%tk zW<1E0f+J1ocWiAN*vY|NJfAiN;N+9ca~Cge7ccNgZx;9<{o5X?<*!}h7aaBk@LBlj zgYji8K5cJ-ycu3SAtXV(Jlv-Y(3&(6i@td5#9{Smz{+YCc zA1;dx;(1b==(>OJWP2sS{ zhMDj0@hi?T8MRqdqmRDedrR+m@24yCib~t3d>8m6CqDS5Dcci;b3w)TK>6O-wHIIB zE^xsLQw}bw(aWRE%W>v%c#8)EUW$WYc!EQ=fW7h^ z09&VZBD+38UwE=z>XiIZ^%TCgc0qk_dj)yx8ArzAT5}iJZt#)QEe`=yil4SA#yBLe zzV=G!;1+)PWE}Uejs1H%tMWV z9ltVXz^5#4%ekjd)s^V`?ra*g%3k2{+31^0jMTc=2Qizh+Bh9=?2e`-z|U z7u#R^Yk$oful{2D@B@3lB%h)>PvcuwD&<`oUs98YeBuR=uM;&;{eIu*-q-6u5bzSQ zbzVT-izm3GJ3!PWQJ&@ts5uVK_EB8gSU)@V^<$SwjvtnZ>)_KN_6-BlL5T;^O02`; z_jAvl+b(49Mgkjf@JtSZVUxdm)p%R%G%uh z7e6xwc;PU(#DVh?V6_Dknn@7TZ6vvX8L13 z_#K8pzX7U?#T&qUXSA_#g$cjoGGyJc-`YNIBJ*`2ei_;y7Q^>&sxD=G)QYiR8c;cp ze>;BVZo9K5IhFwDK82A>Mtd#CcfK}<3_qsI4Q|$jlkDO5U*)gMG9Dt&`G7#1Ndql% zh(7ENEklE$WWn!$vi~lacyXkKs|^5kj%$1`pv28@q-<{x&inAOwsro4L{4V&)vMSt zX}c7&Bv8cHzM%~IX#7z3B3uQ{unj zW6;=JYtrCo-=Gv*<8H+cXbgy-StN-==HF5HPZ=FXd6&LP)KADvtK6;wbPn%)F=3|dP>UV}#J8OkwVA)E-j43r- z(d&hPZ|4mxrah_+ef@e*h?}F*c)R3xbXeu7hl?L-MZnYM)hgvDf+2FQhz0Hba-!~ zeRPrw{*$zq@eSD%iTF)yo_^ySY=@GFny^Y*KzaJDoJoZx0}fwoSNhTM3L$Osk*G2W zlve+WUc75S1gz#TYXFd#W(VLUdO&*SgQx)X{Ed2oG)($w~$oAsddGUe% zrA$@7;Fn7rP!$=+6r7l9SlpSL8wclyc`oNHr~9c<3Zc9@aXMJc_@y%%9!92 zz=gKgOWtiQypU;H1lXhy5m?I(>-q`Ce4+SMnAyo77b4GrL11_8YA z(Jr8RdBwhbu%efiQZGO2E7(fGR$lZL-@4q$(`U(6U$3P9(FtB%49wv0Rj+nN&}yrU zbdk-02g*xS+~^QO1Bl5YEIIO)a~wXv=;pj^=_4Kb7uH}LlLwhTjTgxz=suyBxxM$$l#iw61Fa$#2#Gn1aooh6CnV;{dnM8gH+tuTF@aj zh|p@EJoO3%nA}rLVfU?u3gAR9Tq>Ceip&F4tu01QWmWXetJ4p?cJ$`O^+DUKgp z_+ESInhP*IZaCrLB85)}xubWPA0?R>Rs(7|1~CqaMIU7upam8AvL1MGWPd?(B@ivH zqSfUg3H;tZ;$n$-aFWETsJ7%4p>6zso_!~Ri&>3@q5LFiIsC-G{E6+yfBc_szxa#4 znEc1LpZS@e@jJEf7^{?k)gOh@>Xk;Oy_wuyP3jEz{WvhO*wrase|r5Hja=jh=LR>6 zBH*X3JAY#UqUBnm{M>WT`r{<$F7W6Q`VxWY^80u5=`cS~b>dzAsKDIrV{MTa2ZKhv zpyTf{+&JTd-zVdQD?^TP#CP^yzV`C=+_Rt12G9-h)$QHye)sm)XWrtc)T2%vJdVuw z%c*PGW*mIsT30Q@x6I8ZK9m7UM6IzJT31!K=si1 z1{%HS3B9TFwQa`V5Mhi0=*zaS+j;;$U_S&;n%20VA%8f8YmxVEgE=essI?@Waz4 z_&F|ph2__RJvKFi8_62qU57HmFrXHzmU6^q>0nykyjvd7t*I!P1U)lcRU;N*1?|A1s zx0haic{_LZycfPFS*I`Zs5*Y2i8x@=#33;HXs_H3jAPf$FxGuBP! zo;R+sm3E?MY!uK*i;MFjdw3QTKS+1rpMFcaknNh>c#K61K_Y*!v(#K4~uKhYfOL#iE3QD zIY!UIn~#3ic$jt_P!Adka_V!v?gf3%Cy@{5$m8yc;oh#Hc`cJN;Rm&J2timUIgTpd zLNln2y}^?yr3xyO@4G>&n zy5N}Bs2}1huRRa|xw9TL^pUkG&w{d`vZr+l*gVn)9}7_Lri+<0u;UA*9&oBc<>+kA zVFA3YvjOsXAm9m?ywE8pTB&#HCdKacET;VLTQObCIDw<7XL54Fo#EcOLQ%O?H|BfY z70Jk~Hm;a=LBTEp2hcu#BpXjn2d>spV=B@`w0>m5Q=Wtkuni-9$|t#Kjt*Wr8KMg- z3qY4L7VDRD67cM^&w5w&;-!n*g-e&VU;5<_Z@2li?6c>h3w_JKgNJ&ac2yJj=pOQc ztG>>)=^ht3=nGrV_(~fYLyACVyFy6Ob~5&ySucuL}=0wQPbjZrYDYt3e#oCQ3e%oDCSiKJwuYZ#Qxw zeC`~dKFj9!gx>nrxAxOmBviF@a8Xq~+87zgc+W!qb3gxcKDORZRpEE{+yc#p@4s+aDiLkMzs!GQMyALhj)4!&c12V0#B#V@@F`;50l)-`0|CgQUW z9{h|v<4V4a1L_{?ui9{`${(a zj5-87QNZTz*ov3Yo3#WWW|b{3)Zik!pO~l+(gDYu0H;pyB=Bd>Y9E{lY4lpn!L<#B zP{y}ie-7Y4lP{eh$}{m&Z_s2T2W}OY{;rKp+)OH@&fLgbKH5qDE}h!PRv30zw3Z1S zvfc~{63*o>{_)ppmoA;({>~5o@b=?B{{Pt?f8y~-RR{c(v@t+Y+2ml4NP<4qRMO~~ z_SD~c*b5OVu}mPVFJQbmRbePl_-AG|R-NTQEg+c5o=U9|61gJE-+6{9E->OiX1;)c3!i++ zzRqNJy>?D#@UHc-En!Wts{gcr|9Gye(>8q$<^jKLhkFV5q^Nbq=6(C_ZU3+Rn}6>& zZ#Qq=^vNCcF!yYaoXFKKG0>kiH3Q&|AGcgkmPq3`y3_|FsklP$@lDs`Tl0o*TFC{CgQMZWICg*STXHTS4Y^%`BHHzwyEEiSR4m@YoKDj*;~V z?C7ovVW}>tv_-Qr#>(VL!BaPWga0=HK9CM;b|CWLYM66e)-c*hHTvui=<^-)9qj!a zqss<#>{6m-Uer?ylez-+F(`0RB|eq5!HRF!ALB&3LSx{L677*EbMK&>apu>Ya^CSrs z44P4#3cR(~4M`*iGfHlri5Z^=e)6SHR(}}rovnro8WuS2PF}fu#fv6De_^GHUaE5k&>!J&+4-=`90TozlQzRtMtwnt_UY50k=40A>RQF4oQWTR z&&@sZ@Z7q2D$6M&blT?-Cd_=8R)53u@-F}5!fJ8zCPG=;W7f2|@1 zZ$=ri#+A{FkByCSV{CKMK(m5D1)pFxe&Kbj(H6wRbS4+aIr+I0|3CDh5Bc34btk>T zuQ6w{qKEI@y|;bZyWX{3D#_9^Z=F?WNkd1kE_Jq{IO~tV`Zj#~;xWNsStMmu{pPD@#G?!P7aQMdrwOTSN&- z`Ux-k$eW5=ya8l+4Na)q%JwnrAn;rK#8KYrUNK|rgRq4X=H`mWfuQkU`Pg3VB`$p0 z>5Clyho4_Gx4^Mkb*41cGwi zqAlzit!p=IHH9$?OHz;z1_61p&S_@O9?uXMcU{)dwPdFNKpb6ri;>HobmBz{zaX-? zUf<*Uo3>+kviI|}(AR(PgWK=^-M>2*p0~W9;;Svh1z&iAhI5|&h+$;$E#SFH6uD1v zZcua~`0mGvB#mPa3x?xE{2-UL#?&zsz{ahcceXpX?`3yGE_6TRy`K>jeTgpHjN3w^gq)QU01I>oVj~B=Syd|OP4Qgk3RmW_$r}TJMQfw zIu=jG*<)iTkDEGW*5dM!JIuk+4DitbS9Q|{u;`qA2);1^5Q3lh(Y7_$kzcmRy5@jU zCkZ?H+nf8f9)02?!jJh`U_UAE9xr^7W+g8Qu|=N-eHNMUnChbT{hn~RG1pQ}EM6*T z15b2}(6kl4wyFB;XR6|mD`DN7mAKQvrH|C#nveo&1lR({<7bE9R(1Js4D4mJ`<1kh zujIjTMwuiCn-{3IaybB%{B?K`vd%I&jo1WjfS9e$SZH|yN1bG7_dyW|&ASzp zGwYz3abTFgvWPk9)9@Y?O`@WS0AX+)73znCQ0GfkE#3V z4mM`70f_|wU&X60X>w$-8{+Wc2jwmniYHq|`-Zm38@}-YSBsQT^%HjovfG!)H#Ept`IU%}koAKclf5dD0ME}al1p%6QwH+;YZZk(Z zjvCwE0D9tyC;jUsV+&8(U@-tctt%~%yqo0sHn#Dj_P|pc*b56n99`AfvR+FX-$3QC z#CQ9Fnpr;X9NIr#10+#Sevm)tp|sp@hK}KtzkckvBU#F|hvXd59* zw~la;_oPq$>PM`1twAP{56$wRI~ww$KCoof0)F%X$UC-`&q1A)q3*@3McS%x%AMEL zm>dtr0PTH24j-}-78dASudU(5Ua=k*)Xt*hMS1G5t`oK%lVd02_n@V7vwjl8mW9mw zh@v9ftFcB*^EkbJ?x zB!-pS%0VBpk!cB-3dwb-Fs%A$T*4qV#m)ohZA-4b0v$K7dZTExBl#ex+E_G>tZ(eu zp7_&tn3BKn-1FNPf6*6h-~EUG$ad!*pB85i$-clo;msLhjBQetwhTm{no!2r2;H$o zJ;~^#t{>P1v^{G-ZF3C|z!y<$@|zO){9WJq2eR&;*>3w^!?mLt9BMUN!01oK@f}z; zNqDix(4I=NJpL&WAl}F$LNz>lC4Gim`x$-EJyd27$oLYLB~PXn@!$d_?Vz7SGoIti zvH`Am7&y>Bn>RQvX1=`Z)86HeQ}z6}diZo7;IGFj2qa%Vq})=Eh;dFKUfYM*c;S{f z9|JzK_wzNmH@)R8+gsoM*6o=$zqx-isNZ2q!rVGnETXzslWAi;Y~Kkq4hCTNH>lv- zr&P!*TU7l$a2M10J2F7*sgfadgeS`S6C7yUPvSK(1+choykZ;;o?9SMbX!$JU!8v+QDzdd0?z6t52YMBc?mI+TfnF(Ju1 zwuW9%(?KrKc|JZARW`C9u?M~)_{Ca^Zt5W0eyXe!;&ZSIs4%u(hffLiazjTV$cKeV zFzS;GdhqRuKzUau%N6-GVA=`oKxIhikogD)D}z8i)EPkGn?;}lpn8EZcM9}jC*W6g z2pI|0QTby9s^l=ZMu1+ClyTasz1rh!l=|jK#q3zZk9_Q{SR*X&CpVvt? z&?nQjx4(l6Qtrq_iW64>?#7A{LG2WPM;Eb+eJ_@sZ>#)}7rAeI)0?+%{Kjw0=J+P> zcz)goK6m@3Z~DgV-1&1}e6BXFi)!M_qt57Q-vRL{`uOG8m#)1;QD1Gx?pO-AKXU4Y zMz;4AG&Y;I5k5*h#>Gt@@bbxfpj)NA+GE_4iep~WANE0@J`*pU3?wGvWG_&k^06=A zl|+;zCFrCz#yZXh;9pe=+Nmw-kkre7kQYn^7~i&U6p*tnDZlVX{NRUG{PLIFGGMtn zsyDd=z#a)4^uZ78Jc=CjE#IiFG0kzUV-k{(Fhx3{5Jc|2$ z-~WBv&Fn*0u3R1ckqIA9BHe%Gq&_Mn(V}sh`T{Jqtt$n>#JFJ&OI0qujIFh|*AP|s zs)HEHUaOY5uTf!Y1unYzp`|MiU-7Zp>o;$1pZ|HEw|(&IzOMfr9QF(6&+qL~--y?% z1?@9+>l3);i^Z1Z3GXgCgn|0I6Q>Bz+sXx#)5&Qv%FygI`zbMYz`O)GL zU@w?-harP6j-O<1y#4KO+uq?Gp1vz{_vEp~Z=!f^5U?lk&sxhdK9nStlRyP8jeC0dby{WwRM)c6ZsA%8AYa0`a~Tbpt(LI zS)-x|aCvF;WYT5&~Zl*$MtxC(c80fb^uN{?07mW zDRt)J!gWS~q$VG?6a@*s|lTtP-@6KZ}I`Jdb z>Lb_M0kK1P&){3-;klnW@+?3sP&ck$ccJvr;qb5_31MbBU%bTM2sJL)_U;`#yKe!_ z*01~Vq4&0eRwnkW8B}p~6KrHSI^nx`t2XrJIZ#OI@XvyZL|pYT6BGRa4FTlI<6rt8 zalr4hA{)Qgf&|;yEZDbh-AoK_`Uo_%#^KEN=%f5?PA>GkNW{dlfb{s{je#)&;E(pP z)%F&`MI4NqRh+Wj#x*kB)$aZgBDm;qF{Q)^hiBS`^|HyBMWuf)5{|g=s*fT6+%Ns2 zX3m@sh3|$rANZ@NvwlkdmN&n7yP69?enA?&vmQnO#iSy%N!zi1{Mg&X!wnaA(l$Rq zNW6Fi@AjQL+nb+x%l7-f<@axY;5)y4`<-9=wcF*`<1doJS$)VRabb2YKAum!{p60g z#+Ghq>(%Yq=RQ#xY=O&>1)3AISggA&*b`!Vh9>Kug{VnHV}rOM%Z-mmAA3BcU}hX) zgII83SpR4z%9F^VR6p+1$6UaJRJ4EyCRaV+xM+wtU64sM;etB@qR^r8kg zW4b^)M(>VWWo{^t$N$K#n*<$4NyK2vh}S-8>@lanB^3*xp!_lkjU}?!Sw6$6KI-z8 zzv%MXCUW(TpN`#@*RnZmmhEdwAfPW344|~PeCrZ^7JOXwRypRGu#tR>Qp-0|i zyeuM69FM`NDZGmByh$L?A*LXA8BMa#FN7b=$S+u*r0rPjB+)+yPCeU84&nfjgCBre zu5xzF2M4)`+CndQkjZUV@NJ7^bIYt3gpxT%;&D+D^vHWboVuQ3Bl8YH{q~d6_y9WBfz3d4iHOeJNm*5Kk_iGK5hd$ zwnAGsclC7SsZ+{jV2*+4a(81taXkkKN6W4^2E%~3e(|RuwS(z-Ox2EVA1cS53=>eL z0=A|Q5#o^ji?Xt;VmnshV^gT?%ch_ozv}m|J3(xZ+Yw6{Cm5`IC6e^ z7~S}fp8I{I+KZXdOC$VbC!8jnAT1A4R$rj!AK-@xpJ=|gXGy7LecRi%>o;B|!k)7%6RU0Zk#U^yfr-Vm+XzO}sS}rnxDnW!f%?wVM+(cC7yZ3- zK*A?vsYM@S%yA6Z80D8w)fJzljo+3ap}&v_>wCwKT zO{#m_-CMV}d$;fSKhyrDBx!W-dt(x1X8b-bG}(Ph--`|hJP;QSdlceVo(>|lT;u#@zjjTG9AADflI8b(#>tqVyLtTp6YKPfxORpA_qsMb-cvJQqPww&( zhpJyXbC^a|R!zS2TU`67ewCN93BDw-(vguPa8xeWfcU-kDewoHxF~O%o4jyMao3Sb z*u*uCGxFgv7S&PD0q7ae%){j1JvT#11mTU5h@}u6#yQGXdL3R1^9cQfm_TK*aMLz; z!O;mV$g;ozx8vK9nP(6n7lNdNT#%+-rHco-E)vC;vU807l3Fe#w+OBSWhVg$?DZp> zdQ!os{X(k)NxygBI&t9j!Zme7&alzUMIki)sGd!Z1vVT>Ecn%T|CM`LVEeys`=d(% zXkE-!yTR5LASr(E>IuO?RuruIKN9-Q0&&b2ME0UunD}v^Sze4K8TVvX+Yi+rJ=`^x zMqAplyC-+k>YRwc20oMdlb?LiM{T+DT|5_7uWXmE^waNpNNPNEAk{8(ebgA}F%TtA z{N>NUzJ?$RI_>vY7vpRF3@Yu~$K%L~cjMy(X5s^hu=0Y022MQlI&kc zYumYOf}VY$BO*kBv#68c-pXUiA$5U8VPniD*0F(1zZXW6H3&LYbm?6LII(0&V?%R+ z&n6*H@VD>Yjm)|2>Z4EQVw)e(=%+g9BsS=oVGx@WK1bBO51^|dkc<1lOI<9?V||x# zE>TE|>52?4$vAC z>XA_V!f_XpTz+t~#`mU5D6p(`Kzwq9iD~A?LpfQ$bn)W$_x|4B-Tu4(?*F+x@dUqa ztJy56ulks$ekJj=663Y;D9@(?{PE;WCj3Dp<=Ca2_wjM!3vd!9)4;N^Geib?IJ}UB z0FM!c+}yRMQO>*kwms0E;6$&ytU0Wx4pO1U*7zmux`g%+|?8T9sCXY>d3HVRPDen*KUq2ufnqS+jwQ#Kv3 zEgyRf&)itG7Do0bb%*8{N*UMTxpVvW_MUgYcScfT3w~bdE!*olzxqDl5D&eT$wvPw zlU6^q#o&_du?aS45>ItqynJE1aQV`9;nKyMPYpmW&oY=iW3KB}5^^Yq$Fci>U2~MAW;QtGnO9x^5Luko zQ&@iRBH+DtAfjCb7~@9RJS?7%w;lFZaxVshw+W$0&AamiPI%2iQ;Yp^M-f~t4w&oF?4C+PE2Mh#Q zpdI+bD@z1C3C0IEg1lw`ls5y7#N>cCIC=FeJe&ZjBYw@MpkilXN}Y{^=Ay0_ANbH; z#p@kI<`mz#@xOsVFj?Wt%l4$scP0U}IT0*?34~X(@ar24lkm&U1%Qt>fD1Rgqp+V8 zQ12!T3t(J=uZhu#ta|Yes{k}mja3(YVpe`W-Jw^}!6L%o?*&q0mk_6^!?OMOx%Rv8iaAcPN`Z2?D8#pnujk%K?F;8iz(zBQIo z$YEC-yS7b4E(Xt?-9GZskN63Lb~ZF9nCj@-!w7Ku~CAedW_Aei?f2gNae4S~t~D-ZOuN7FM63 zgJ0I9&-9TPWQ-OYjPq@-RQNs#2FuvbQJ z>Zu-h%R`lR9oA8xa&ERPxiE!x@R@Nl%<2Z{htA>36T|9IZe&q}zTFRjzQ9I&IKtDX zexeq8o+LuaxPXVJPzdGXtvog+LDppH1?&XFdO~~E1-kfU+pYu$IehYxDxK8KsG@hcM&4h$D(3hN;u-5RYP!$IW9Z+9V>U`DYpZ)WHy8WHM^TXStk3JH&XgMrx6OVC{ z^S|Q&ed1|i zU-5EUZVr@xa158lCoU!1Rlr_tg2UD-7pV33A6UES6XaQ6*|QSwVO_D}<>SM7^(#J+ zjr_+x_Ob2P|N1ZAzWJMf-*z*5KX~2BvA-WdF=f7*lK#Asy@LOPHMSwva{8IJE0r8y zoeQPAr;~imTo*6Pj-v_%ze<9KM}6;k!}3-xe!uEB{>JUMe9hNvFTC)AecU*8ycmET zQl`(x2u~2eR4)sJ6Pp;V5vTc>C{Pfl6vVFVW!m2K8t@N;S?lSQu zI#zSmIy%+T7=lx$&n}$5uzlX=eO~$>u2A5aKDc}Lwz}vWJs&~jXmvF=)=QT9deN6f zr53}Cb8ZS+4i3GA#)Z8OP5j7FWt#en;%og!^OA#214-kYkUBn%U-ArJ&kLqsc3D_Q z9vnQugY!ZcymWjtro zz@1`p>PJlh=ef#U!>A(l7O7MR{MB_DY(qd^@?_W$OSytpXvadfpQgQm6>r(8&(ZVF zDFbSPZ*KMp%U|VLb6BfJ)96LMAM~U|jKl$Jyd8AQn43?5530Ku_^IxPfH-s_53&P3?;S*w7zFSK0dA@9x(tqi5hOgryZA_=QIvv9 zRf+(7%KL&hvMROah6wXen?@nB-8ehhQ}tJa{p2eZF8KJ=kP9JBL@JbQwDIeMPd@pC ze8msMKJ+DG8Ivvuv~B5WJ9T#!jl<&9r2Do7z9nxJ?(kHfF*gq6oB$s!uG1gd6=*NK zDtGbXB#4V1`6I{)0`==RZbV%aEMIcCbm`J|H79DF$o=#Y-4}SwC^-vu zs45iDKkWj?W|ThRg`Y?-`>PEdpY?ULnXd)6yeq{veH32W-a5ZF(&2XAv1uU=7Yo#du>41)(MUl~9R zQ@3q7PzQQE)X{T*lv9_a40-vMAG?C#UHsh~2RCrAIXZ0b!SCbTQU_1*B?Ty?Ek|<8 zg>rLPrKBSpiyyqv07oC8U>B*3asGki;GzcF-)l~gWSe-`s9fr|7TlP!AArNUl=9HpkCE^_$N(ocfcijVpSsup zg#)|L7{WEaM%MPG1MrHI;5&D60-iZR``LH;{r|Mxe(KuFO}Zca!T-#;?fj!H#1_8j zJK>29_8b8JlIc74K<({acu75Qm&23EwpNL_otc_cJNS$aec}WjImCErBXw}YN0s%% zM~v-OG-YpK;7y&-q_y%^7W+w*QJzH1ruV4Hw#JYBPlFcysEirbE55oiy%{=t)BWw< zox9uJJNLZV*dG;yN()}yPVQyhyn8QlcU<>hc{^%e1qh36%AHu35m9qWR zeG{YZneJ1=2c>&8MZNJQ6gdf)T(;$XuwJ0Ujy-fG1w;SvLtf|3pY3-}gZl&D{vF#J z-}r`{t6WbTiPgx37yY~zxE_arep}O7=1GTkFaF7+o_^x{@%X;ZKj6T+Hj?OTJ|%zCo8Fjl(HpNq6f;iP zFV!s$Jy@*Gj;lbjB^Ck)ngn zngi>C<7^ZxmCC2w3*IDn9h&7+`;5Qco@~&lH!h9A$itHcpaG}$I0UZ`5>S%@I63Q6 zNmxxH8&C$lr*Pu~NbspQR`o$Yj$q-ynsSi4Mn!sK$2U6Qp?zUUnH>G_tJ^}!%>PQ^ z(~-{C;S_iSYWBT?0cC*DIU;;};#oxKlr2P#auR`#SnqIz=*Gg}f;P&Lr+A!82PjW* zaEk>HGiAUf1*#x?Dv3|CpyX&th9DP+@6Rz380O0!7N*ZfsaW05BVqLcY3h_sd<*S^P>rd^1!Fs&p!KnHlhB?YA?+6q}F5WZSQ!yI{Xwd&Qw*XXKP@O zZ(!YQ&>vsi^$jmV=m@_29h>XdsNHRtNAn0?jU=h7;~R5*R1+V1HyOROg|@3N%<2E9c{gAawLH-FR<%QVQ~N}2bLYxt{mjDCDfjF(Iqdqu4~jd7V5)- zs_LXU_@xnXK-YxPkn*lAY>qi{V$K-ScIc5;1@$D^onw5O$2tg07$WQm1{WUGk>jO4 z$$M9d;D}g|@GGJZr3pdO=KzsCrddP?P#9j2(Z{-*@g)`ej?Jve)E&RoXE|?p9Z&M2 zJ2@n1l#}W!^2IM5=mhUcgUF66)T5uaEx(lmmvqVo__fZGk)SV~0p_1^0*8*^)XIU1 zUpc9mDAxQWr;~fiGLGFTh8#y#FFf@KVIiyTz zw{PFu-kJUCJHG8(wi_>BiwGBZ?L&P)MdavTRYm?>#s&RD{q#JVI4j1hz^_uT+WthI z$3W_ojcYNfka95AMJblDHbjmFa3RVzx)-#TwmQg?$K{KcE=u9zmh%??%kUyj{P;JI zH@)di+oj9%_lChk=TUi{bh~`z3f%66tfBfdeNx}p_hv6uC;9Tx<3M@g>G@8_1_JJr z$vgJ(zl!uF2hSNF>W3`{sJt@DK|I9Jc@kBNhAY!!jt5Kt$k!hjMh{~r`sGjm%gRA| ze4!btLQlAuqak^-(y>zgj#1WaS(~H65_Xfp$GB>3z_x>7WhEgqbmmajJ$~DzZAS+@ z>>>D(gkR{?7#b=oUjAsNoWxj>jGSDIU!ZntoI~hNNTv#TecZt!?QOptgSINteB@S4 zAoOc62*YG-+B7dK{BY_-dbm9{{u$I?$X@h`32q5pIWx+*j{k?nlWV^*($LQ!{ z%HpLeH=~EIT=l{Vt2L^{9Ak^9*RUBAnsUi-QE0p(M%Zm>1jRQbzX>Vt8>U{4ebhO^OebfJ+^#;N$KwL;&zI-LP zbK2d3_KvMySVn75dWYR)`jzAj1svTKfS+Q675(%D3?;OGDdnL4byEXKjMdMWqP!Fn z(-Ths9?Hch7oab^@JWA2?(%%^z-yrunZ38#H z4zZmcEx$UOqieSxG+Y#TDJKA@Kv=&X99GZ^zC0`ALXh#j+RRvk#u$Un9Fl@xc`;-i zZzKkp<1o0Cs{xzDBFKT_3(ME)0E1r~GqPesJbb*gl?r_e4#w3TvsO{GY(Ygk?DJM0;@>BK+v2Zv*8)HZsnkS$EM9UiLu#a_+zWum79vpZv3bx;_2` zKS+lRjz$jmi6eTG`pFSC^RmdH`6_y26R%RoH}Fdy7Eb^{(vMl!)e8*~+ZTXN79)He z!*N10QmR{d(U$P>8&CK{Ss8SZQuZV>$(W)-d|$@MMJF|W3t zSM5?se?%8#F9d?3!Wz8xFo3<_!i9_5Sw2y{cXzva{rdLDzUPl@U;3qAvR%JZCaDWKFg0j z-Mn*m`|ZE&w{KtaWnZ>kd+D0y0sPWd^!pWw@SnTLk3#jojRA1_HSNKhz9Kh1+J+Q6 zHgw*k9QA;-!PA#`4#kV?;AnQsRN+17HAjhcOU-GlTB41{ME=tG3w{;r?D@1IJgmVT zm7T9h-$^{)|2dz%UCDV0H#yM74GzcP0Q2YYBXPk;mJ&MZS9vMpL-WWmc;y$JV#-O7 z)2ib1w>0Fq5#!Br*1OQXAraumM%6of@k+e%tRdJ#(W1jb5}-{LTQ!(hV+MZpzdpMb z%NTW)<{X>~u=y&ZPoLzBX|xQ};tg)!#;D!mFPpEd^e@fBu!D|CnBT6mNBWKD2-qtf2I;__J3vE2#HGWR;1 z21Yp1ZLoT{J5VBiifXUjtOi4v1Fk-J+X+I+O2-%R$Y*xi!?=JQ)MM3c>!lRJj9C1#MXGg z%WL?-EPN?d*aaB*sh82RZJugR6gWvZx81tc$HZK;C%)Ka6Y8giBM;yY)@Gs82kGIn zA7l#7LTQm1ca%M78)Tr^>Zmym$ntLQ_RzZTDCKXhyxVGfD#N3NeCLb1{AbUGn>HYa z@8RJwsw=q&=9gG|vDdMCh_wzZa|v78YXdZD)`h)1*I$0QcdYsJH}qb7gzTbPzz6Rt zro3!ug~dI5`^g1(@~n2?*7vXB;eVWa#}=;Q+cx~`WBdF^p^8oDMjyW7Q|+swYCK8c z*E3&D-!EIXA+)7P`$>Rt=s>kD3n&HP^QfhLy;;0gU~a8zLSc{Z5iH!Y4Rh_IyS(I3 zt*5Y?!iV8e2bqk+OL3KhKkx?H2myR$2a(z-USKw^*Ftde5*Nlo7_&>% z{LnYrYw^g=z-n+n71VJyaNuqGy}6xOnZp+3>H}oh$3FSV7q$<6-Pdlv`|H1cyTJu8 z(#o*+W8t+>`PwVT*u{SI>V_!l9Sw+_Y76D5t51a_-yyZ{4`Zoyf6F5LL(YD7Cu{tL z?K{5pTfN}&yagSs+iFT2vJdfNQFp@IN9m(8ZD0Nvz9hYvIfZYa>s#S9eGw@6H2y(8 z#?CS5e|Rcdn)M@F0Hi&oe(&UN%ACt2Dtx^sj$1}9O#HjTlTSXr{f4jj4aR`6Ts^}R zi^e9gT=gb+7B6{H(9S{nWQXFHOd(}-!b<^2nI&W4P(gR0n*JnjDFpqe9)M6{09vXk z>C=ucEPpFpUUknnQTISgt6uxaAMnekV`ytkA)1dZtgIUX$`!ry347e8eK6*&^kO0h z{a}oj9%5q-7F%GeuX{-o)O8JDpDzQ+IyR;%ek#kPC=MVd4U1)+AC?dnsV?t~fs|oi zwKYMHAxie~ddv)Dz$_Z^g;pEz1s7T4yT<=1;ldj4ufu7`$RL0e30ec!ljIJbo|G@z z;DhTxPn|@k(5VkBX4YI)!kZpz$1qT!kgBttw%|}IlzR;TF?2RX{S?8W#dRX#V%-g{ zw?eo>61;4YM+e1*z&dSPbfEK?b{6Azd>D+$Z}{n2XuT{B<-Qxkw;7@7C(6+$=(xL-CZw9Bnbno&ynsT~gmjgE-KO$|U*|C2IPP$E^__Aox zPaMvlIk&xh?Pc4{McUdI*?^yT{4x0y$pIcfX%(%u=4C)+3s9c+>NB=!Q~HzK$qf;1 zbf!|r=r*DH2X6v9{aXgdBNv5!cj_FE$dw5F*FN@fH)Omx#HIe8oSfJ;9{2XUdJSI2 z*U>^dh8P!YHiMRrO(9efH2dL{D%N(K*jG6*gBpC=m07JnJ76oyh~?@x+qv{E zLjiE!=}%di!4*;)T!A*wu+b}F@g8gm>gZV5@w;Ah9BBow{}0Lo3*Wl^Pwsjk$`}B6 zs<%Tcesrd;CiDi)nqg;^qz~5OmpSz$V-mz_1Gs*oGWx_bhr(nVX3PYftKiWgH>AAw zeut;*l}FR?=|}mrv1}g60{ccDy0!r94PMMbGf%0&OI;*scnJz+s_YZsDiJ76y-E7J z0N=uII0udYidaEQ_sCr@v6?<-t{{v^+Yp=Tgb*CP4n7P#eew&x@Qd4D`9Je9v}wZg3MzzQ@VaGt1Tkt`x?$zSpQV&O_MG zmdtTGEGNN5s*3gju*S{O*^BX^<;4#-E+|j&{D{{F-v5E^xBb@Ny1n$$OTi=-q4_J; zSz5U%%y{Ag7#qxhJtjbkj?LujQ)2wm#|Y>z2kJ)&sDI%d{spJ>C+l=qgPKo`Q-NA_r7ntlQu7H{jtC>B)Oj>SMdXccCgRL2Gr5TCC)V43)^w+yv@N>8GJMqg}z_=$P@vnhFi_ zg7IhZSH76SMAG#b-teg+F9ne6-nTSx20~kmE%*vpwk0z*bR`ErR7xG`DkVo-0pdbB43UEVk&`XIUx#BzJc&-DWZx5D z=fhElPS!{UFXMcOEH2eG5Rea|ci~Fw0GYej;E>w&(4p`JXI|cRUU>`PT3UJ?NPDjj zFL>L~y6Xm4g#v!zC*@g;$Q7f;#m+1J|JPLesKrD65C$jyK8dfY``fdhd@eRp$-vDy z0Y=lD#3V9Y6hHbX-`RrDBlvy~AWMY?d68mEv6 zA2#`}k@8wfdu(8nY9rsjhnTj{gwp5rtOS-*Zy%)UVuueU`(1Ayi9uKD&ppe3&k_vu zB#&c!s(I=1<$a^HkE7p5G_uj4iX>ng|J4nGhE;B!oeO=%CWq9044Do+fvuCZf?K&tG{X+kZZpXkHnpgF)@4Br@uS&bE@UL&|H}C zNEMG*@dIfntJNsQ74Jr1C*{bq%<}_OT;#4F3S&WIVY`?M;`0~I`^nG6i|4oVxkz74 znJptK@P{$hMG_-@%o?8d4Z0XRH22QEJKM)T@oU=j#K$&=Gc-ouE3fv%4x1;OJRlU^ z_Awem6O|Ys>LW-7Y}+1rQd7_RZ?v_KgKoPyWHxM^2pbKHw;6 zxB6;y0X~hNgQrdsPVojey!xC1sq!MqCZr9TDxRzwhX-6s0f_ahI)lRB-36j)DTz1` zW9q|j#M=VICf70gEbEV(IB}e|sg&V)nKp-x7C$kfg&nfu)GqOm8l56(>Ns-1DTMBPZr#4UJ^I)q>UCO$UNI{esw{v`GIH9<#A7WI zNkgZxK_JbA5VqNu^uVFdni?_IIQ)qmea{&1@y*qL(cc>wwS&#IegNGsbToQ7i0qo$ zio=z?$u&}y=%Ib^!-xNfBT*^yz0WFl46*|HRxKcHVQ_qs%a0&2HuQO3YD+9$dhx~W z>eWZLKl^9?+;-*RtK03Y@qS239MZ)Xd31Q_PMqdW{7>#a7p=`hECm;k?5ne9^PMPaI5rY4HfK zUTFmDA9jOR5jcDa4|69mt)AjLo;iQu2RP4d=hAOnq%pobhTx~K4>GGwm?@4z`B$5z zt-v5Vy!(yB@vFK+wh~*;J8aSZ@-;3kJHHw0;6@)b>8S%yErvI5ljpgHYUJjCHdM5dxtD=#Jg0IGofjNR>dEC7>Fu(F~{WLq)=TK^4#j6zPoGI#{102Z1 z_ySVec?-}gALI~}C8`Pzb28CKHdaa5rDF$hQwqMt;20YZ@Q=>o82Cc5{M~GnPsNqr5LbOn|nw#JWInhI{ZwT1U@1Qjb^i`pE+8 zj^n?v?i8oZIpPEY0+{e0I4)6&bH`}-=_CtU3hqj;k>7U%5dg@6!%=Jic zZHX9hT+S~Dp%!bcX7ROs+1K9j@~~cY&l^O_jD@x%y6W2KoR_-l#{tH#skI(!;FhlB zv1HjSeb!IF#{R&vp)xZ1N=M36QVzs$Ar=IMuAvxbZU!!1et3*^mrvHYAqlX~qvOW) z8-CsAd;jF0+CKf=@7b>3y1m`KcQ-NMcQ5YgyEg||Ns})dt9{XK>@d|6^TOVKj{yBK zCC7Luj3;pL5)X(=FS-uG;+gMU$ex^VBUa>)?t30W+gPXX+~ZN;r?x-x-G5lQySb<* zcIo5;*u)r`lKTTQJMjmG3Z!gQm(N2^hB|=*5?F z%}v_2#_x(LZS^-atd@^HXC9pmjT;2~R?6Gn@y`8M)rqwi$tkY(@syvMXCOKz9Z2XT zfhRtcBde+Mn!z`ILR5`o0bJ7JN#T_{cl9!0;Oi*mZ}T=wezC@Hn-ohI&b2Vico zhIb9?*s&C7u3g(2A7;&1bu*d3k);rRZpv}iCxbRix4okmFf5#JA*149Ytiexo_E2R zWB87Fdjn}DvZWhe(Oa1cV=IYjrv#h$}_wwJEIp zbvOlCCsvRePzOb-jaP@rKDfj~kQfLqv`$!SJFkn&;OumH!Bkc@Hjy=8R}$b&Qt#m4 z(^iHs19R+7}#aWjba&KCzyiot*U3FGK|ZgRt&Vu@^Z%>hs(KCDCN>p* zSfdMNVgu7&VR&0lib}Ow&0*{>Us)V#haB<4Mejk7?9ksk zZglW{UqN!XhI}rY%AK4L+{i_vznsm&nirocKKaBGexlhEHKeNU+&O;Og^eh<=-Hcf z6kCz0*6+cWV0Fc7#|{6^D-Y7(i>odRiA`g0tREGOQ#SwSpMQRS^>a4-0A*gp;<3jb z->zQmqtHfI)j5RMiwYK=ksD{GEaO0Q=R|99=?3-^uOIzKKeGMY&;8u?s~`L5_G3Tx zKWzW)Km5O{0)G$VxFF6?i&Ba#8z?@*)v?3}-VbfpUVPC{sWIdyR7zGRShZ$;FYq&l6KyME%4&R1A{X^*xGgM5WM=Pw#x(IlfQWVNWJX>hu$P`qxaY^ zCQ8>8%Hcy^o%`q!Dgz~WH};7ET@0_ftCRlH9(qKiE~)lm-Pb$DG`#71<+Lx?yg-!~ zxx*R=M8XrUkyvN}=8mU&T050(ELXfp#*FbQKqMc2%O3W;HUsPtLFqpv(WSvc>bb*; zEjS2pL_i^`s~w(zeFWW?fgfJi|Ekdz73}S6KQB*MYQKNglMCRSh;!5J@BZDt zxBcJ$(LdUrdip89%XyOa0(r4J;*01sVA%jP&*$q3?^rM_bHwx zDDV<<`jfw@dg+rdY~S^r-?{zv-}YO!TdCs%H?>dhz2dZBf9IlI)yekpQ7bh*IlXh* z-L{p(j*ooDQp(4?D|RzpprLxP^#Z%U&wx+FdKV9)Usp*H9KTn>`1$Iu{_5>(f9Kb3 zH(q|(y}ZAgofxFg85jFHtbx4svk6@(=&w9fgM4it%PAa6M}SPT%A`@-o7f^ zHW$DRh!5TN9N_^cUT@N!(Jxgj#mVldn*{ITE+LIF{U) zEnCV@Du!b?dHaM0?K?22*R=^$C1f7y(|}d8A&;B@Vr16X6*aiPk1RE&dZlRD;2juxjdcINBrgk7CL^2t9>xA%mb=A5;|q`b$AWT>bfA&%iHf# z8MuadAGE*o5^-cmw(h)F9)9@8Ul9?6bM3&jvV~AzP;W9HE-_fOK7jCO9+oZUY0@n`)XOfI~k zGad=YN}R~?S1XLmSJOtoizvo_%C@h_*qXS|-X#7jdB6AvXd{-*12djsFI295PK$Ch zD+5PJ;5wcb#4gBVl;!Gp5WqUlgfK?wf%6DI3J-UB%Ue)Oi-Gza%&r$|=6>p@aB2H~ z5qgBD&)c>Gf4ZZPIxZY*UViL2cpX==4<4TK&GMw!N_6m{X%lyn_4!4887VMgcopb% zDN(#|OLlLsvK`Mr(beZKtCA0INgP|Rz3|GOa%isnxy3hPmF z26%uutA0?j1n-ctCcgk(Tah19aSP8-Pe-KAL+%iE9t_>XUY`)~j4?eWK-$Qp1iC-C?BH4c>}TM1S5E~!9`gx}B!#~u=7K<<6S zjjc5vk|^m6F;xo<*Dq?UL#363{AoDEukC6@-6Z7@6s_0eiZ&hu_onbGl15;6U4W`D zuePskJ=WlwNdZ0z2q!O3kF2jG9%|v@=(%T~-~PS-)mLr5@ArN4cKz0^_IY@j*L(yq_eM_Wbf|zNkP+L!}r^_?{2^En}7fIj(5CmyLIzMc=FP4^{&UaZBYb`;e-8x z!hracy>J#2sMu>@;a04K6dK*?T4s*T$vXn8-wV+rUg^9~f=Yb&r;Lneh_uA-IY;jH z-P_wEk6hh8^L_7|?@mWJc%z5^;diY_j+tB6Z`HX0{R2^>hg|dZOB8C2+L7=P>pD8_ zGM=2H*}wUCgumZBci}uiN;&qNcW_rh`(ca>6bE3KaSBA1s^w4=AuhB5U>#|nExt<9 zH;n0&BP1`vyc4J;-95f^&Y{WsLCeH3>cycl23!MF8LZ)XcK`&c@$imA2vOTrSWL9Tqk^`+gnN*zoL@%2Oj~B6c@qGdwq2b3BT;QYgqJOWz zo!O{NSb2`0MecBMhJAux8``6+Ck0ANpGcG~x#27CK?jIE9xFC^*?&pmvdIyeQYza| zZc_|_g^I^2FPy)SXfSDmi@5eEpFNWe<*twHA-i6D&y^E49=(c&aI@G^%4_@vy8t|~ z(Eq&aW2%f5^d^ClbL0^LA4iq1zR4MT+6&m1)Kd%IVS^Zjkak>`Bbl=ZKERRs1;XjT8;I6%V-7>%6d=fcM zHc9jlG2pxI{5aRy^XEg?JBaFSoT)Po&&L0>fksZfj}XF48z%OU$!A<)r?{}8j0#|# zAd#k;gEp(~2s$PjK94hMbL6^wz9Bo|UTj>drML|}4 z!Uk`6m*9iE9_Au70BbcvA!aQh-#M9D4ai4Q%P6R+e!|84?I#Gt2|VpeA(=xv%&R#aT^Ja6ZERZaeo%ipRzO-EpdX2Mbx2lqVixB5g$~jYfVV&#)*M)h zQ)7OkC^`BC^n*{4xub`VfWm zfO_MAdIj*&lz{VF4q&126`PA$b1!8s{_-z=X!}e5$zSp$`SK+`f#ilHU)!L6tH~TQ zN$O{g?)dT)^rDGI_(isugOp{Pcr}8xR|WVN zo>AgC8WR(@$>S{fGY0z7G-G ze((_oqoe;v8vA+cnK;@!b@0+A{&W(tnEp2MGFDE!2vwRqB4)X8Twb7j1q7-K^gA&i z=CqwTMH4QZJHMUJ+`+Gtw2vSD;``C>`Hc5&Pd)XNpNi{q0^a=)U5U;lVsQEDWzTi` z;X(U~1idbdQv^alHXIo*?$ry890d6*Nt;03o;%Tkc}}=3G&ro?87^K zGhn}vc%fHZV`9|fNX^rh(IHn7ZAnJ|3dj?Wr1o#Da)6zA7k)J`rj~35b;JbwD&RGM zMf4SCJfavM29tW@)MY7}gMxv=)y1 zgN{tOZNo?^SGJU+Z)6rkEC7y(Q=hSv`eLmgoX;KVM6*(X;5|nSo*q`0ij&Yq{Lz>J zPQ3gcyRnB4{=>Lf-ciFoJjQJiUWZeVc=B2SWgvE<18cB=2eo%fczgcE0Ab+3)L=V- z<)u@S22Vj-6x9LdNU!|K@gYndMCGf28H@n@0SC<*yhE)1H86nsrw_sHkGk#$#7C9` zZ4NK~GY@*#Kf~1p5rHnOwDiE&OWbwWhhOo8#=_>B#l?2Ysno4z4HU~;zlQ%Ba7kO#L zR~K10Sv*th#!+creH3PYwu8L5<#8;gOK4m2@4FZ$rZHEZO|sujVHh;LFlr|laE0=aqetHL!cOYt zK1h@otWHmTirA=Q)|XB}CP<~D!*b*o6cJEK13Fq+>D^ztGy{{PlrL-C>$t_x3fTecvDd(I+V+Tz}h1o z1naBq&KsUdNRiq{6w9kks?evZ?=$z5T0F>DCT6AD#}#V14x0R$hJIBRy(?DBjfSCq zy>e0{Jp4B)pNg_~{+U1fA8c=U}D9b?5K{ve>)-#Vd^b1lEy9DaVZ(*8}lbMw~r#N$sm$6P0oTkCJ) z=m!o*Wj+KzbI%=^r{wUH!w2`m9l$v-dI3tS=G>W=Hzp{>myXwMyM5=jec@FOO%5G1 zl|SedjCtCaOpVx00*C$fPiV>3oLN8{%^hRJ4!PJ$&T7I@ov=ZI3rEstN?MNpDwK}Q+Be)H!ailP~4uVt(=$hzz2aJ56yhjsEG_v3+ zA7DRO1g|`vv}(7{;8c$)4!mOyq&Or+RgJu`%18mWVc2;C>I8z26**<`pxm0sfsKGV zn@`)DT72ZfijdrU&|C9EF&-m&9de~&ph4j84ue9r=jLlR@i?2+@$p@mo zQWt`AA*9@H0BND@lMikIwvh6K0$Q2mTKw4IN5R-6NydoD8)`jZ=?qeEFz%;Y0^KeD{WvnU`LA(eDHI#HJf3 z!nBJ|2>6?lejm8jFw~p?8qvzZBtG1m#;@}2K?%)psJ6Q7mqyzL;(%~`gH9})%aV{QV+6Q+70?u0Sr2)zVsT(KJgFAxN4nd}- zVmKbr7GLPK(l}MV@v8li_fY#*N50YrJbV^+KR8S|u$wKx{Gb!rDF=U$3ItCbI*D;v z{AgD$r6}nK%4L;EgyD2j?yS=CNG7IO8qKXRn`Kjtn%*r$T;dl z6c2j!&p^*%dy~tPkE}C3wwgflRS2kj_q2aagTJr(!$cQy@$y4I^f$ME@vr`s-vjn0 zDVoB=ckmepK5;ZYFIr3ZRgXm_;UloduRq|(cu7@W(BRDTX1v5?V^1FpX{Sdm^w9i; z@T`ZBgs7=2!)zI#Je5z8TVnCEv}+3~^(0U3M~8j{@Xrg}aZtaZnP^}8hbm7d9bXK~ zhyQ2$z07;L=-_*px0C+FAODlv2R`@nw;MNa!xT29OzXxW@oId~Qe69h1dI_4K_?qp zjaN;|UIYwofvli;NvkcnoRdjmqVA_cDPx~*?70MV^1zJGuD{UJUd~56S9x{&gWvUC z+hdPDvfa9UvwYFd-h&SI6>M=sT$9`dOWun@oLr!RWjLLW8l zv!V`2Y_+&}d$G!xXKeDJ#q=?L#%I~pqef~}jxy{7Pp2>P;1o+6vDtCCVEPgK60)8+ zL=T)96{9y5{KLgDv6_oXkxK{V=qUaOm(+bd#h}$|-vmK9$o5a=h4CNIuZ4#G zU;!8eoFG&m2qwY0KuA^6v5jL0evCPoCLJci;K@n*iNFDld68X%D3<{HESAR^d&C=B z@6s_zL)K4DII_vyZyNwLMCbME*WFBvmu~k_=ml4=UX_<$4(1{Wo34Aa$WYf7eykIT zS&%t;q7f%lDKQ6fWK-}LDbWdU@NR^(b*)skht3_lldL1-G5o{6+F@N%IP6-GNHI)e z8Nb8CFDaL=5kv0bwD}y5fa}977Sjf7`{_b>8_W7-KiJ56gd%gs4JCL0bCnEz$%9Ky z?9`Kr3l&TSJk)eb#G79Q^*gj+;tKuqiBEjO|9(8fW1@UMs?+hE@8Bg4PdxGD_VB}3 z(l$CK?e(Yb8;f)2`&UP_0bArdq-Y$haD+zNatt0n__30guifyGWZI!$(f#H(K2u)W zhNDZbjfo$eX;aD`>P341OO!c5>QVw zKm3Yl+u2V;e0(WjYvu$=4`RdqNdnc4u)G}uEyE*gEg^}f0-vzBjv&KvrwE`97Xqh2 zyD+Q-jNc-p*Ou*(hgt>dH|5#~+HU0LghiRyA6+wHlW2E8Azb>j6>-)p=0oQM`XFb- zAQrv*#ykB34OuTV&^>7U!aqYv^wEXh_^^NJB03zy*hVdL5_f_^jH18O06lztrEY(h z7tErY2iJKK;RV45tuaoCzy4u&ipxl z{?f)T+G;1bN3UGo{_#Kl$J_tyAO5%gim#u#1#g?wSRYYB-Tu$Gany(lHiL;VaQKez z^oM!qgjwxV7a96eLe`vq3mfC#^(twm=o&-FP^64s z)IIS=cL=;@Srg=^4-{(MoD`HgBHMEg_>4x(;zLVadZ_T7+TsA`TV#3EoWJ|~9l!0j zZ6EwyADj!|v6+M&>c{I%+fzDZ+^TKncKF6$W5k7u{f)W?IZ-3j{x9|A&Z`*F%cscZ=zM);rv(&lq%U*K- zKA#Y?{>c)R%mH-8PHf?K#{?X;2dt=hGl)VC(o|A9cH4a9;Tv8sO9HJCAO)p;7CnkQbf1rk%5U~ zvq(jb`5#{ADZ2B59Uy-t!iWeRQC%Mfa9<}^g*sT#))$!FMMww&6oiY zXAT)y%vaiD_NE8zpgSmp9 zPCM!niv-b>%J3G*hj(U=lX5|DP7No~Y58t^$dUja)9XMgFMu4W1AEa~@Y~U+c{{Fh zIHk9n11$wNZXU?XgeNJZOW#r^OHMrM7xjnyVW^Xw*j&1B0g9WBkdu$|*<`r8y8do~ z@0s?$X8|S%c2b-Z>eegI{F>*ubq!(-Td5`32LY{i~GVwLpPw?5N2<-~*Ub*YC%I0au5UmscH@vr1Q ze$TiIFTZYi{pDO-&qD1Fo@O3KFJRi9YkS5JAAx@|)*TQ zwKCR#C7+rxBEBO}tV|$kgMKiECVM)0=;%O1m~wFF8TXuX7UhMZiH%nuOfZ11vTjbJ zg9LsQR)r1?Dg}|q$UFpaK+3C_vi+id@=7%BtZNy!(Y5q?0-hMqUdD4}B|4n!3tV9! zu?`R~cS5zRd&#d09r~2-qxBP;>S7H*kA9_Sa}sM-<(@=wGicUmbnkx9E7SihGQr`$ zI8;OioTd1uu$AI!2dJ;;#18fHRv)lpvtYkTvrv((4k|(Ja>J0E5@}iJ0e|Z;vg@X4 zF_qP?6m949!vad(qo|;u*hCphP-w~gL=H;&r=C(tOqq|VU%GU~uOr;J(Hp1GnA2-M zvc_D#d};e1fAS}{zy3o%v|WAV;a;eWX*zKExu0AGa1C8BQq+sAG2-Bt2|0TgGx2rW z8(#jibKgU4OXUD<&8x!bPK~h@9=J>#*k{Hqsv6?Qi4y72uoQ-W+ChavV2w=<@Y=7C zD`>v@8hez<)#aRkkrduGQq`5<7;CX{X7*_0IbrAb7+5d)Kj6=O{|B}|@hAV}b}x1R z0*^MKT8RKLeD%bwW(Q2>z#a%VM;8N=*beGGr$YmpZ{E7S{f^)MJGL+RqA%QDOdR?* zcxPQ(Ilp1w_6Z^OpBPfr*dtf{LMGQAtHVTJm@^hCzw-nP5irO-Oe=p4d}_k6Uwob5 zBp2+p6|3=quW!Bm?Qh@S^WOJ#4r+)#O+H59YcXwh94!+4LgP}=P{6((3*rv4heiQi zGglct`xWLS%iIGLmugl@h8!>NUCV5Vmj_{lqmf-l}5*QW2tgh$>X%|Y- zq@VNT3`IO7_gpSD>|jWnA!M9mzj~3!>S|;C(lG{Ubk?r||I<#HDTl1*-{?_q_>!zI zTLZ=KT2hZ3xRiB&$twp>{h{g zL9iX`NW2aYg2U<%Py$8g5-o59G69t~X>e9jGlN6aq2nswPFcKy=ypwUgHPr}YpuGF z+gXNh;MB<%kWNQl5$%mWHye@SsxtTty4_X^YXTV(S%iQ%+Qa?+TWRt(`W2ASO!}I0RBB#nzCbs0B`h zuH~ZM|BwuLvYcXd@OM{dw|Bntoem3dU?Gw4&f$fZiP2Df1NMzRP}aHe5uf@=(M#8O zWVv@4xnKf_{iBaP=Ed^THG=vFzt`)_*7)UJWc|*j;YnWQdDN2c6#6OD@bXC96OTXX zFM9LW5de7O1!Q5>Z{iVv|J8fZH)Dmd;Ynu_zA&3Q*MP1WJq)OKl0JeeLt`|3RYdaz zvUd!he$4(s2r`6&uG%T{;EqjzAB6qQoAD@Wt$RoGV5TZ8+yRbkgm#cEZ}~^gV)&`& zSlXocz;FdO8eBsv-aZhhS3xswjD$%({U8mEag)4<0@~@Z`cr=wFJY)G2e1%GIZ(GB zQin8TPvB%9M5RxI2=FitViakgYHFeeIDyeeXvo-pQlYF65Ag!L8AthueZNVYI%|mW zlApL8XgaX!0Xg6W=f&6f8;9tt1T8oUQ;!7mgQsJ-=z-4vn3eb&v9cN&++YO1oos|1Ox3AsSx+FK3LgXQjr-5c$by0dsJ zM)&L+&`pYfC#3`;g+AVk&HLNU8`u5b^`HLJ|G{?k(MSC)1|M6mX!VR46xOe{!-#~z zb-f0}S=Ls?w7)8W`m>1WK*<`XNr2+?X>5w<1%Q21qOs_zJ9|tKJLrOO%3GhnwQbA( zy~Lh<``f?e+tqiH3rK#P4V~hR*{r7>St`F#$HmvsBo}iaI);sR@ zPtr;`Dg>hIxcVT}(x-;Dr)~0U17Y-{$9}rM-M({cd&`@j*&cf&dnz~NVMGR=k<-m1 z171W(0-3@PJI*Xkog;{q0Dj^lJCi z3Kv^R^@$07#;RkaOxDH2OBEgQ(L5N}@?|H!PVt}@#6kwDB`Df08u{^sqA#(5#*F$J znYFv1atfY;BVTtqIBaArlqK}|KuoEJSNt40b|_K~JGv|vPmX7;5)W`GqK8VLd*9-n zyaKPo1F%M{M}xGIxI^&wvw&mR1>i3aP+J{@#idgr zgF_y@!&|@>ozKEiUU-=3yZz8xs$c3}Fcs*?F^E8|jT~ERgXGh;SF&M#@{^yG?x$^G z<^-L`W6zxBZfoqK4Cxv0r+~XRL)RzB%A_!DGf|BVyihM5W_`@8dF7pZ)kJ^h3s^6Fyac z!yC3Ib8%{aD#17|ed#m?Ri3Q4oFc0i+Vz~^@hB$o|_0)G>$V9g`aM)Kcxmbnz+^T5nrs>@Rsx+MBqKNZYXV!fSy; zQpcld(UeVE^#QBuX}nq|j*EBj8g9FZ@X~9{rIk;v;1;j!l<)UZ!qXdXX@%4i&+2bl zk5GZCx%Pi0;Kwh}!%%`%f25DT3&`Pnuv#OLruQ*+^0qpO;Ic zN;I+4y^$Fi$~BU4u(aaCVy4bf92%>;KCm`auWI03G{vgKqB!WHh9_y(mwKDm^sBr9 zE`oXTJQ*8A#Fx5SUJWCw50vQ_ z@Tm|mBN5E-7N9Yod1B|F1OKX{8pIP9hMV!7H2~r;@HLkeLwp2kD~WcX%X(mRl)os- zH?#kJ{^x(e_H|$TwcE9qUdmoXZ?vtP*PJ_Z&ZpU|a}x$z=<%f%lRDAeY^MU{hzrK{ z01GcHr;Y&3G4{dw4)~OWkNDR;ta#4TIA8hP4}3uX@h#|%myubXtXOe=xPLk*q(GZ# zAF?~Xu;eO$FGo1-#SWC@&Sfg-n$}lu!W<;t=ESfJr6&IpT#%rM(WXg;^B{&I-^v zAtUtD8Jut|y!}zUkJEv&+}<$c!If9$!gO41^@LnokQUy_1%W{sP4no_QUlpe9e*() zzqY{iBEj04I;*u@Q!YLvVbL8BPTE z#lm(|N*RDxp4Rmrw$v?WBb3*7aq?vodHMQHe|30`1$;Ss{vjXfv%SdhDI$JmLEld@ zQ%9?d;U_6ZiAUb?peZo#Fc{H+ph72h( zi3L9K;)44e8**?T{phcT9=SM3{CHgJ4NpAj69qn+7f?eEo)k5}>d^-mKjPjv#1bN& z)bV#2j7c_DE_Rp8$aAs8-y>bVba5f=E29P@WBnY3N@i-+ISk@l~C}@=F@H%I_y-!a?5x?1NG-v9kgpnQKgO9aqtnGA#am zO9zHy*T)v~k{IyQ48~m;IuF}^ijJ1mHkB=Eit>t*(7M`7EINJ{ zZulw32hg1-$l`l>s&~a>V!A_hPI1bSMWzEQKzU*d9sL{}qi8;W{sOUe%Fc+p6OFv? z0VymktOs}r)PDq%qc6&dr|W|B@X{fXK%Tm53JEQFvj#Bt{{G+p``bVKhyQSU!yEXI z^{(e!81o3{?IgF4@wq3j^c(iDK@9PiT4#P(Lp~dZtp1c;t60-UMlN0JS~r7FEP7l^ zWCkG~-Cn@JH~HZvZy>mR+%6f*)U32X8!S_)ofgNYu;k#44Fne{YlId0H+xj4Rdk?o zmk%C76t71qvBCexvbOp|mD#_qzjST;hTrphwhw;rYq#6C`XtP`^XHYNKO2i^$3FtO zSIFWo^u!K+EZ2YNv>%7$gphK14r3jBAJ$K-S_ACBf(&v4_=enQX zZ|9b09B54Hn>2Fyu)@An^tuRYJcxIyC51B;7*RE4_|}>r7wykjqF> zo*0MF3#Z_WUsHLK$`Y7yq&L`3uH(TmZX&zvtbReKy|L$rX7u12uZkD;_|9v1+O5^4 z9{3eZoU{YOYG?h>t;p7-6>1)pVGb$}P7BkP$eU4zckuXJ!+FIoT(uTpFw4_A#p-|< z4D?b!1e7WxW!k0gg7VFshGsju0tM7IARFLbt70L;cfwoKfO5K!~iv+=>Ba)xV0>~$2pehQ_@J$_F zA-RJ)sIsGrWAmkVK^K{FnlW-0UBrPGygm*;bQY{~#DemrX+OG{Wa4S-ZWla{|L{Ft z7CSyg3sdNRS2HIT{ACW`iCw@_aKfiOQ3g--BN9#McF|kDF`w? zFUBUB7wXV>>HoY2$Avn%x@`}Fm0=NbA;l-ug;#e1UDyN2knjmx>DTgd1gh&MKeiP4 zbIMKJ^_NfV%C9Qy#TQOmEz)+zO0|M;ZR7${SCJDL4h!fOol?uls%!Du2pEP}{)ha| zm!Km2fez8Cea7Yp?#7K9o*enN3R-9^&!0IPo|El~#~$~QIpiEu*hYuzAFpVO;r(U? zpd;l)kg-PHO`yS0*Ga|__BkQOm!7=b_mgM8mmD=*D8F(q<12Y>6N7M0b6{fc#5Vr} zYBNJXmV!RhmouLAh?B!t&u-^0UD(cDxDa}8W&tdktBgCGTyhTB@l`-KG4#Y9M`)iy z*eCY2Qvg@L;3!a`25;NdO}etuX#)*OncOE5tdowRc>8yU#);SJ_v&h1-W3b_0xKgw zeD$HeS2l9?&#HqOyf(=3AC~HuZkcL%Nnpy8T(OdIi<8f)6jk)1 z&m3>#g2KO)gZI;t2re7tCm!S!Yu6%UC-SJ;eFC3+wO1YCXa?sota$Y+5$*v|s1Ev^ zTwU-M8k?0uKk^I4oi_zGdUa9H0p4{HzxXY3I0$-FuSE{bQKd5^Qx7kGLPK_a8elNy z#9uNHIbwQ%l+#Y0B)M^$^)gzCqbAUCe|zNWmF-{r#7}HL^tb-j_QaEq`%Ccj33IJC zuLoTEuh4<1!L_JcT@Qnt^JewRT1BaEB~_$`Ky`rsU` zno>v%;A)V%dt7LHXobOpT)JSd1>@@;7X0d}VL;NN81%x6ybuQX5lV7C78_GYhL-@c zrihcGd2V9zcXYSz+}xgj{`u{TzW58bKlF#bYrCB_nEz1cq@GxNL8l8`>^rUV98e1A zPl>5cUrP)uy~Z^9ctn^n!6VLh?%vy;dg=|^cYNn}Y$?Z|hCG2mK39fMeaF|ztg8(@Vj8#L-;R~d*YJISz4pTZK^^s8!s!L3Rp`f~0C zm4oLv;M_xsYx|DJT{4QRie3&X36Nu(xr?8}s2&*>t}?}v>Nh~G=bHz4u#_8v@J`>l z77nj`N%eVT=s)i=QeO}pbz>G9I<$%!{3dU5jgU^culCJA$_{@~qhpFAmVEG0*s>g! z@o&FA!ys9b7!@~Tvh;kNO8MhSZP;Jvf?3k*@Br{5mcr@`!GIqH&iJHn*e`~&vnmoD=s^=b}8Q*@{^ z37;TAckjaV;6U_Kja|4!_#E(5XalP#Rs5{pJvJ137zj>uZBJEvA9G%Pm^S3qp)m6B z;u{m$#f7wO=g*$s&YiswHa5R1R-oR_tiYRN07w=q11iA^0O?P7ANByW>jG-K>cPwVy$YQ1aZm}(J zywoPO`nKdj;&1(-exw&jb*(GaTlwk(zu?d|ft;e~<2DCj2Ci#>7sIMW|B`REcy)wI zipH0;Y@w^Az^)4UUBI8leP?Vl5h-jE5^ z`3~bG-tZ-7ev>Yo>#xUmjPykK;men{kA3W8+h6=o{$uC-l`9WB=j_wusO5Jh&Y#U1 zbCySU`9ZDSn;lSzj89R>P!1!Os&=8<&(nu-Tok+CPKIwZ{}-EAf~`fS#EeMvpErC$G|e~mS6{KCh&f8);W z?YDf**KEJ(H~z-$#TP%>@FuzE8qa7;)_MrIWQ_V`lWo97>^h#Bj3@j6OnDzyE$4tZ z^#zOPe;K4Lugw2(<5~Lr`i+;jcYfMCwkIBc+#AU|BrpeitAJJfUDlhoei&!g+&6}A z6s^6mOI_OzDCan5oRr5gw)n?BW6&oKM^@~x^o9blRk^0UNXD;JrKQTv13VNr!W_%f zit|$W_EB+13=4JvE0Mt-rOGLTqVe^hqawvIHWn`9g)uVYqfY2ZQx~2AY>|is8He_t zYuD(keOA%NX8|Q+=zOXsj`qp0^@if=#{<4F{Uy`~WziWv+J#gJa$BztOHt&H&R6O) zTuLg7PG2Kp-wfF2@!xT!_%H>!rpGVafU4@j2Cp5I8(DmP9bN;OGwCEYi9;_m5A@DT z3Jk#MFfRc1AR|X7cTj^}9R+W@16u2Ll3W=;$z&}%>P_HAMG#4;?0hf?si0rJGGk|z z&DH>R)`jY1s0aAG{5(t&D3$3#!!J9Z-7e*VS6jjH<4G*|pZEUH*&cuNk?ro?+g>PT zbxnS6d-BOAwzt3iZCQl-DWh>kWpd21@$|%rn6n`CBxT+0bv)y1c$Z&Rkmofh+NXLe z69;KSh%ApZ7carARW2T|6~2@g&RmVf1Kw4q%A<98ap8CM%2j#kT^4LM9Zur7+lo&0 z;QO?V3G5Fvf!7Xg<-xCG2!G!6ffs^ zut24V#j4Nfg`XFFsh{;>;TFGxYV=kH`{k#MzXvFeHAQsz;Urgka7#~)t!Rt23Ea>m z9oh|a>?ElW1aYf-EwnC)gB8XIq!QM=-A|^6jy>AMxMyrEz!z?IELgT|zd34hXk$m$ z&`$x3)!cR_B}cz@cfE@@Hg^@l;~)I^8+>C_d#6mHhc$%tJ;n362wr`~#pI<6m$o~1 z?rwki`@esC_7l%;PjYh3dW@#5+4_{WxVC~P9+Brln44Pbf(qSd_ym9gHRP0KOfr6} z2esve&gi1vm*ZR(d_@;nRk@z-3jy4zuQhf(dR*I-S3P`)1P{xpe&l5pEKH)C?ZYg! zDphjtms1d&_LJHv3$&p~_cKA-ev8T$B3iD~8#T;-L`}AY4X9Z)LWQ=K7 z(SmEz*j&)|SI*c|2=KKSd_Cv5Jn(VOayR?nw|>jFc$0>UN1kxId-BS5=U#s`+Z*Ou zj(syVYnp@W7}eCZM(kySKcysT$ccmL0IN=ho=*)BJ~ff^C!S2g7Gs-Ux|egb&->i> z`=~n?$BkU&Pu-LcAm{n4iF*C+#il3|Fd8NmY-4z<2f5&M7pp1E8ifo;_uq*{`={q- zyp%;BSm@5vyujxr!^GQiKT zp!&zM$)oY-1vj*QjZ-;P>DSWnIvhjB;NDXM?Sw)C>_*xE?j5o6;49B3NWHKz*a3Jg z(FgKPM@moG5wQS#vqCD%MqpHmYnPYaMT|)a&teKt-g(nVe$svHIX}U}l9#ODywjS2 zbfhOsl6n2_)W$oT-h#Py0X3b&ChI~|GA&LJ@Ld-UP$#c zgh#9zUogNrf#6Y?)duv#&oE{Ic5)>*f-})l5l>qiyJ;UHhg$n9eBAYvA6ab29@B#c z@1Gn1_@GbKDJpgRIyqrV-S_dRlhp6sKiMuld~tjHiO2mxsoS?nx6}4Fx|sQhapYCU z!AEPeiH3JwG(f_agEatN>cJ;B>WU*z|JFyx4&1*OZ>G}V^Vr`DMPLZTJY|SKHt816Rp04iDAbmXUtQN zEdBv2%-|jbdBDS@?PyN&d#)o$?k6Sig-10glV1FaLuD#=fW=!r%EuR2j8}L{D~eV# z3r0+H(7HC%hh=Y%ML_$@7GEy6z@hk&tS!bf3F=Z2yfo0<$YHcibzO`)0v8`_$}*l7 zE{Xm~-ls88TV80$BeEVJUU7zpJ~tnK+estUi#|$>H^`*C_Vrn=#%t8omX*eT z`PCDx>JgXJ8x4|={3@c{;pavh{EqqR@+jX*+`vuy?}sn?p?bTPU3 z%9OJ<;9P!iw11$6Umh+jE$~0EbBq zN%pzO99}#Bzd95Z{r-qV(p$(9j>p)ATW5_Io#lP96Vv><+&hLUyYsg zg+qT3?s1gGpQ~fkMUAxdl+ZnMnEJv2)}$v7%bN4uGbT3FBkS)0jU2FiPzOP+p!{H1 zC(*|XD7rdyRsRBx9XlndcGmfuzVSjPqp9cJg_XY!r{N5N?XXYh7;J*K!nHbz4hG6c zvO^pw)C)+l5QA!m9XdwpF|Q^%a0<}sgLrw%f57oR!ZZ0I--%FMVSE6`;5gICJ4OR+ z3rSXKGda9T!5Nbz#;{r(bn&f>*+}kf4?q0q_N8C?<=dBk#aHBl_&01{`XyhwJ@)vM z{-9P{jh?+!-7U2kns@p2Nu!Vp!7-^o>4N^IlJ?p^A<#>0LwVH|ycZ3sXl#`13SzW@ zo}2>MW%FiZ2io&`620paCjUMtI`|=tbLTE@U-*Szw7u_r@AH%IFa5GF+dk{FKHJR^ z`-REl1Abh+dbQuTQh#3uz?b@?xRbVi(7&yPpku+8Ag}zM-P6%Fj{&`PM@sl6Qf{hypoGe^<_~G>Pm2Cd^eDwX~)sv9pYxHx0$ggIeKgW-$ zjE^-SkcnfEWqcCy`cWGF^~q1ZP#BfRcp!;1`kQfFZ;?^=Z`$ZQTNB%O>~(4c*MNH3tX%02qzL!1*U%7|qoz2kQb>>lysuN)o7h!B@V8 zTWgdMQB+!$250CK7Vj=+OxD*VV#7;;i12bvt-r#!*IIdp669drj8i@}7Bh~tKgNl1 zV&6y~Y<4^ZGdAoC#KB1^9fskYR8Ss*CmKush|_^bVIu1ReDXkZ;*f&=!>=NV#w2Ck zO;becEd0K!Q)`n)p0$&i#Kqaemo9GqkN^I^-~P}4;2&&Hzu}EhlX32x9$%L}q&2kq zxHwjXeVoZo{Kz{Vyos}yp}~(d@n-(f2k45uSzD#q_|jI)X2DQC<^mcV9I;Sw%Za%m z!!y-KmvsO?LLa^Ep(}|Xrj&Pq!ssqES9NfBjUl>vkDGWnb5Wd_UrMa~-HOru$*l9g z`Ky2P_O)O4!R%Orx0z5pI{d71-9|sG=1LSiUPcufiab2bjU|NZ9|+AeFHPNZ1a~cU)nC5 zzbN0Ri6V5XV!L_!_V)F^>+84Ac<+1sy^3Ct_3xATPPJh{VT5UezkcsHYwExpx{i|S zv$YgznN%6iUBD2p?52fZQz5QD4UV_K3Zjj2QV zbYvHW;KdDp>Py9;4Rm^;6Ny5wVd_9wd_d|oC{Lj}L68-FH27H!C?;`dnIF{PG2qKr zF2m);fwJnThQq+CeRV8Iwe;Gf+W~6;g+mp$9@^4dv~}gl zQ(b5-{O#Wq@xhx0As+gqEo%uJbQnZf9}zbgNF+8#em(j2?OQ3c{Ee&&ZB9zkrbi!n z%)d6_M5!A+V*$M^v~8P7?HD14r+l(PW1*!iy}+OP^C`5V;q)RmcHZ>nH~9#DKiR5$ zeG6AJ6jhE~Lqqo%2%dJq1j)Wz)X*GD7Do?|;5ddN0JWPSvdo>HAUH}#hMPV6#vY0{ zOpH+%-ll=w&WbZA_-1^761`*?cWa)E-?njQtjeAJKwGGt*8mj5nzU~00HT#8tL&kV zD!<0rYQiFm-+8H5@32?Tf%zy4E`|Msn(|7;RPF&;9m`oMkO`F+oPPEi9@lr=$Bff{CoXh)F%0#0qCI59|p0R^0g z#QvkxSGRTyh~0^i3(+fdymGZ|E;VX*qMh!TXh&2)oMQn31qC&nI`ccf=k)jU`QB?k z`}dwxDE8HV^|_yC?RBqvUiVsi?cv$a^Gt0Fr4(J<0QzIYN?*m9v6Y3u^v9o~fzZS2 z&5{*IN+#)w3;o8Q_AY}O(IP%NmH>1Mto!6s9N8*LFTZl)qbm>T?l98CMh?7U!BFEB z0@?G#S0gYQKXc6!?@+H^xw8Gh5B|gLJHF#jY!5yB(02LKWxu!2Bd67?ZDY0tplS5N ziU4u@H8G8*n9Qj~jb*rQrft5{8ku$cSnBn?K!wz$oqPfqq3o@0p$XNkeQ5C&(&8=} zV#Y!Y^Mccpz@e@fl9l1meJ;ql05(1D7Z^(ZV_^Bg*?4$cSGFZxvL;TIj+Tqby zHCT5p7wH)4Lc=ct^P^xq7S+F!>Mt$#t|n!TmF-n!qh~f^jCFEbLSV_J4sEAHHav|~ z6(GO(g5+~lFz6TbV3M*yIkL82=5dqr;pae}`uXRdH+FtV%ZnoxoK*aM5$#7G<%gsA z)##o)^nt|qi7!%yU)D}s9)TDZjWIJO8^y7W-xpuFUR$BjUv8p2n1gl?q0pK$4(RRO z^bw!hZ5$4)gG=71_>LR@dD+JWi2?cwgPI>j;RnqwrmvikqmOm%<^{$GEhQ6FB)}-{ycE{fy(XxAr01>YsFh+C}E9-QAZs+c-Ko3oKcqD;ij`r#{qH zVU6X`QmC1C^>-@Tq+%ZdalZ;xG7QRqebAiqV2CZojLo6XCn(w+UZHvL#^%sCu>m7$ zKJB7UJUP&a3?!xFwZ;dq42Uv5I=-W5i_*B)0mYiv6I9i^J zr;q}3hSSc)9;^BNiXlT!GDWc&ad6Xvs_pXe-Z86?F+&TEEKOs`Ji31U*7o_o@bk7` z@{9i+e@Kjc`Isrf0gm^?B3PU5BSMDm5s%B@?ITO0k_ z2{xfOpI+33%-AA}sFvVCR~o&c1=|5KRq8=IXI5VV^riF4rZC~8Zl3U?mql+?f3b(x zb)LD_327y?orZbMT(J#z8LVoXx*Q$m?irDl$ANwRS8k_AuTMqTaNFF5rW`MF*<4FM zawCl#r!3RJ?k50B zbVop*XI8YD5YAs1JF)K^8X16=6iuA`zXm5r3P})ykOYx&Mt>iK6K(A<4(MVBF|A2B z=QMsoe3(JCDH;Hw%z$T8S$LS}30h^=Nq-LP4kogxsL^K!s3~n!FLVen^gja9fsu0` zMIRn0^3;_*7vKF6qR2Cu{rA4SLgSEIsp@veYa5l$d1RTKI@+Nj;w#0Sp{XxK5t;`; z@&g0eRNNUn$gZ5t(iY(2`>+#|M_$GbWNTlMhZA48N`E;EMUPo`Rh;whZaYel_tIM_R+NVq56@-g}fB=vgQdngbpou zXkNhQozqU!eE!0P?W0dUwegGJv|;yqQsB(IbK7H&Ju1Dn5CSLepj-ft4|35Ts5<2r z5Km)2V5UX|xOx3{E`nc}yT+xi9~onMuTPd-+_-KZ8Bf-NOQ-lEmgFSkwCm-?iA&Ha zMfSg>%I5OL%aPi)haP&+KIAlEyo77Wog3(R;+;9=xJT~h^_$)2vEY0jeD#&F!e21I z{~nCHx&5C;T5xI$xsx8%;sK?1eJF)C^Gj(1q=H8OkcD=iejD{=m71b#<#~}mPwqxT zIcqCn`SRw3vQkF~o0X|;fY{;DPAu%3iuHnK`91@xjt;qbMSs~wi$OThR$SDQp-Jca zVvX0b6k>zcpgU9_V#iJcI}O$Lp=A_zK19}~W3Qk$Z@d3#_j})!e&8JQfjQE3t?ONw z?gW+R?)X{2OYOHByPUx3YxNHgd5wBo0p#`5;&-m$Ppr;S?e^x_%Y2e(+KFY`E}XmQ z4_DPEu~!^h{IWYfzU#aG^!8&v_M?8if;Geo3zV}z*2gPh#jJt!rSWuZ3;1Gu5aULq z3iE;vf64xx#JSK+zbq-C9KJ$kd`EG0KTe;Aw+RNMZ7jJC8{hPjN`?OE{R3Gnku7yYGk3>a| zG3&4y=Y+CD^RjXSfj)_(P7J{eHJv!>+V6n9$i_DRrw$&1UmuXiHuU5}3UZNg*)+fP z-D7o#h{qxJSg|{wYeS_JSMoIulgH9%#wPn2b!h0%^|B350|V%AQ|;b%;qs--oqn|m zlib|?`Ty3>Pt5(1Ic{9}NO!;slI0iJ@zeU!wAH?`Ng)5=L+9%bj!#SFQV2IysA;2` zd7F5+ZS1%u$K-TD-Ln>ebWG57Y>mf}p0OU#Z}&atMZn`UaiIfk=>DF8aWTU}qe(0( zA&`y6GtS6GzWsr&f%3eum@^1Q7jn*Zx1s5V9HeNfcE_A@;v7F_9Dt*& z-AbDlzU_sw=rVVq%MdrVkrg}M9G$8<$i{|)(bE0~bKeV+7`MZ7zwbCt_ zX&)xWgRJM`<9Bu2)XEMa?_T$aU?K9Ho2T?ptN#As8@k5GUd#L-mf^hyXCSLZwn>l^ zma+!WtW%XnB`i5%hBq5`L{1Q9Ac1A`NNaVpktxBV>)@Sew3v|Yp{bS)Js$mselTS$ z%1T6M`X-*znRs%g0(Fa(`az5-{%OF=q^tcfUKmtAMU< zn(v-84*wtq7y~qRSUW*Eiq+PT+n?dqY(203E?-JOGJwijLr*?vSEaVbNYUUP90Fa? zUf!O0`st{_=fn&9*zFjBKk?|}ewrZY44nMToIuKsh7!J>>~rbM9$L7uIBubFK+XmD zezPQG_Jb#$c%tp7t~~U6a1qg5a*K%>Uj?l~k1f4Mj~^rBQ8x3U2pe{HzQYBLPs7jU zq=48@Czt)NO2bKwLv%62r&in$3O_p6uV07i0ZB+u`dN9RCjKSRAO`B+Tp+%?F?t-g z3=QtO`A{6*%J-71b+vfKWM zj()0{0~9GkFO2-s*JL)!%zd&IU9`sJN!%i(u8AHD$s_Wx?ZaU%5|w@OvNP>L6sLwA=Puz$+V zzCv4iimcehWt2|GGZh|CK z_5aoRTLdi6Vg zUwP93dTHy^oc3Yj9QR!UqMy=^Th2_WGL)cEy(Z+Qa*7aYfO+wAC_NpnK7GKDpSO%K2X}=t*R%ILLA~Y_Oh`0K(uj5GjBm` zWquRGm}H-U3h(Bv+uOU|^{(wJ{#UN?-nYr*N#ScnRJAAs~k+Jzb5!uoMrj zEN!>YgF$j$?Nnc`$?`F>Xo#PcgQzSoMByyEwAMZbWBkiQ7Q4uXdF*eG1;}8vay1YV z7pDu1D_~$JS!0~I)ayZ_c4{~UXrBQ5^Fk&wA~jaV7F%v025qZ#dUtB%7@jk-)F+GTPJ`jLfxZJsTxnCz z&=6w-IXgIu`Pf#U6OZvG}Cv5W&sWT@drK#SH?KN)n-<=3C4(`a)h*3EMQ|S=qC+R@6%uG&Qu8MLNMLwzkGs z+Iyc=htt97dQ)G>3QJ%0+7N0SL>o3`RK{3AM}PUkM&(ythmP=CcLJ(n+t5yQ;h?W| z^s!HS`4d7>7E7VS(^pSKmxvcKpvsm!mIH7GBoY72b%p8wl8V0dg7&p`nuJ_>k6jT!Pg(xv?TTZ_an&beLhB8%m1iK^ z%)5Q9TJh?KX1s?7l^E9zwAC*$5&1_;XR|%^q^c6HJ^B9M_Wtwe~YW zyEV|U6!!R2q#dm+oSGc1_Q{xkBj&M_AGW-iW9cVspZ2Mr+V6&kf4l+UnC*V=v$bMi z8=>agW*`V+OIgvxlcsXJ(NP$2TR~h^u$eh`@!|#L;jgmhj}WsowHq#5EKPIh1%G4< zFT1?N=+|E+jyw$#FLuUayAK`P)88FtJ|^CyU8@x3mtAZc@ajj3{wNA(bA%9gn~1f; zrDW^62QY5!w`L`s`XEhxHq)yJFHzgG|F1rDpHfZQ@>EJ_&JS*o1*X5tZZYIiuw!%R z_5mz7vc^$aXubJ>EaK3qM;F*TNUX5vUoBK_@tYHDoa{{b=t&xhUIV;jSuD-xsE6hEGSA3T(eA?9fkH6voVa&zVGNf?b5;y9m|b7XS24v; z&YV0ehR{K*s_$b)@@fwWDgBI z8+n9_tnx4*)Q%4|oScsT*iMW+@c|~@U4Q7Q+6UTmU<8PD>4)|b_UL+K1yo3DG-R;^#*R}^! z_+BkgzhKxRKOA)0URzSvz7hxVLT&$<-+tPhJn<+tC&IVy+|I>n$Bw(d4?p}+KP?)Y zq=9ia!r;`{VN9DRD8qm!k`umrcm1D7#*#;{s)*c*i<8Ej(8NF8;8(6)oD;8)7)Cr% zjYUp&iu=824i0(oN$}mfeCIeG@4eK=L5;gQ0&3EL%%3@NY#bCCGx*qv@51SZ%c+0J zfY6p8I2ucK(Me8~QV|tWi*`D=Ee`At$;p;1D!AHlJ|=;H@CdsD0+1#`r{L=Uk#C*e)nvFC|PB;aW?{`f{NH2S7oEi1Fe zY3=jNjvCrJ`I8CF{wbLENpByEjA2E0&Dz}|nLV_TqmO$(Wn$X~A_aX9zTz^L#0wqu zU4Pmsb}fuO9({q(_uAy-+9i#rGZ3Lf9@T4Cu5KUv$)DW5?c2Y@PpA0Qm+#@9zi=_y z59DI_c4T=hdisEN;%c8*i()0V_+o}pbF&N2;aikvyp~RwdY+gQ6YK3r8nTFuj|U?_ zzf(J++JcUO#!!)E2ul3U96f%`rTscf(_X~+T1qKAx;voV(PcBZ^g(n3W}nl?e$3(rBl*O#Hc-K0 zgfa220Ul3`=cKUKdVg1BY?eRqTfhT~F8+e>!zP#9v?gC11K;!R_iT?m{D|`c`3vd8 z%DZEBG_f~M#E#+V_*Yo`(k7M4b~mZkI7*$?ph&GD@jT;Rze2%`ILBN&e=+lr-ykWh z*<$|4cO7@!%6v{p}b1So(CRbF=#Rv&P%<9eA0qiP(9YufcubG(7HHB(iCqgqqYs6P(%uujoM1 zt=f?o9O97%I`$nTaR5e&va5{feQ*6rGslOleH(CV>nQMjaA#Qk+-TWDqzybub|%e3QncvY_t~& z#d{MTWHQwDgRyhi1L*)f7q{4oF)t{HB_bT~dc$M%?>*p!4|iMnCF8Ck*lL_RkXI_V zaWOXcc!@!siN|{QEK+Ir1*A^flMv$9UAdmLkcYG}%ju^FWX45R=%wz#1o6P|a{3XQ zocw6ivtI1?2dW-@>~ZILOeICx;>SnlIMCuVc-Cn9t+VAIkxl;aufM4av|rwyec`#- z&B+A&68%e_`Aa4~ow(~Ga}m`pn~6<`{9#dBpDMs@77G41b11#WAY0LiUqcCpA2xX; z7u;OpKmPcm@q4*Bu7D>LbgnlmI1#WZaN_;qi!bCNfXCrtHk%7MfcFH4!x32v5LbBB z!#{DCQ9bYlM0@``GMxr&q0!tI9_K1sO*{t$7qy`u0CoL zd`Y-}-7g+L%l^qt{WA`lVk}`|3z-tD0IuHPHY5ndQ1Q@IM$UI};uM449PI@WhN!~3 z9eB-GPF6Hg3+w+%-ILtkxkS#s;mIXpJ&{7MP{Za4T)W*@A+5-~0jW${+3yA&xz#`X zF|R^j2Yd>?Mh^Rh^g%l{)C+q0i!ThcZ$zLhLaGOcls(;%t7kBZ{^~O z+0K-C*^3XxeA_PNLifh?>)Rjuwr|^h`lo+tyLOEq!b;Z8pYsvvOMI^~YYC72^7R93 zwIWABg!p6UrOEzBY!z)`976Eqc>1&VOF_maeCSKbKBgRDawV{n173vBoH2)ynZ5%} z`N(RRPv450$AOMv_~c&k#Dl%GlSMU&rx&E9OUp(%`scWT2A{P>yQ2?ZEH!jKY3FMo z-|{=ZWqZ$i-@84Rb&7Rf-`FJ(?(S-@@nM^}eB;KA;H!_wAlBSBh~<0bJaFi+Isx;) z*Nqd@Yu4cO*S2ea2&y#>+7=}XhQgR2mt%vR$hzODTaZqyi5dHVHsyrou>ghoL09$Y z=p!4C_s(VJ>xHcI*SF95jL+J>_=~=Hd*KDXQytm059|PbY=3+pcdF{V`6piR-KHHq z0&>X1XMD2$+$TaV{gge0DRcAsjqM$8f1C4{<2V1tzz^8HDj37~<_<{%G#`GK_I|)O zyu1ucY{oL6r7)Z;X+VbNv6}0;jGI3y>G=flB`aZhqukxPBc{2DOZ(sw`&Ex#a55(q z2_^i58>+IoKKrtWv#|R# zO*$=_I_EU*i;?hVIdFT2h7gs=W;PM8RF$RTBz9a{2LSYEj0EM zeKcRC0u6Kc(vRW zCs^L;QegfMU9s}KL54?Zcn*Rx8*SQn4ekT>3o8ZySlfNzrMFb1iS6WIvXXEnBqB#y zYBPV51&|FLnp_5pQ5)LQFQr?+yM)j?!ediZnmfhF!r-OZ(69*2of%mcAerH4q;mRO zIw~RGouUMZF1R~S`9+_dLMV+Ov@1X(XS5d$YNvSP9X7JbS?~1Yuh1L?hGrg+)drBU zi~;XvX@^Y@mSDT>kzRQqhOQ_x4l#f3LiCWElTYkjxY!?_fZPRm#ucc^RRv63QL3H6 zSm1ljyOtTL&{qC|*r1Qlc2_PHGY$iZjm1D)>60(QUS}R{q{=dxapK_4uQOlBMQ~FP zALn28Z?Ep;B8mSNEF)U+e%%xe0*Lh8P*%DfH!B3YB1y7qRUN}_6>jzj`ta} z=|}0vSGRDIl{RDEc}xLDHqEsz)b6t52tgP?zuF#vm)yaxeG-eD!t5Ih(8LG6nvY8F z8r9ipOP0LU-)TH4s~UM_3sNGBJ?hg|N_!Ub% zc;{(PWYY_6oyKd$1wc1)*zdepD=uHTwEfxt{6F8m_wW9_?cs+X zb{}$I@=;BEcYlHA6BI#w62lG=PjhvQy=!IpylN=5Cz8mn0(D+tsgLNXIt!Q_RNgLt zUHTRb0rRlzFCp5TW#X$b7ghx93-l_yn%lvXOc2*1@&{hpveJF&U^i>|Y2FM?KGg%R zM^An9quW=1^;d8I?iYUH_ChX%;B&kumz0hZK8mA^-i3?jw=37KO5;^nw!8l|4o9iF zizdCahSokU`7jh|J8_Vc*xdb$9IuY^&{9@B(srr7gqY9@<5NUg=9ala5}C2nxJMgY zCJm@1DaV+?2!UhYS0$&fd)<@Uty?#{dqj9W{{R0S;59`%l*E>1`|Bofio5$L;yrg* zxi;GDd+bNt(BOvCyWjI(^*qjUaYLofNl#mJDEjr;c~O4>S;*F>IjLZ@86P>CQZ#e4 zBqi?y^zajVv7sN%VNwh)w0^iSacO+;gZxgPIHW^sQvijAh!=nH>HMP)>Mt9KMg7C^ zTkZN|AJmAtZDKZVT~wB0ouRZdUD7^9+NR{<(E7^;q&ne!dXpy;R8 zhq4(<&OM;vdkV3t2&B3C3$1;o*|B|q?~8>#VePQX0W&8B?WO2KEZSouv=xK;DN3kb z-<}`R8uQDGHMS$%n`mca0%cfMT>62E8!5mEdks$DY$i4C;0%BZ0&S~;IB8}S(qIrE zvmx1#p+JBpPYDb78k~;Yv?Wy^yC*pYc<8hiUD`>XLUY}<0j$Sv?byh~VF4?@qNP)D zV!uvQVl;)`q@ir>@Y3c%A1TD^E87}qthAM1+(5~t+eq1IEK!by;kMFW)&75Fvbg|mJklg>%PDuP?rx&AINllwN z#Tp)c%_0@qbwdGq#}50gOD`Pzu%J`1GOdWfC{iLD#3H5OHBNZ^YUrI?w?~nMMXoqX zPdxeLQdWjMa56yQBC|JTfcWu56bxtt_Py_k5z6!-vYbqCQoM9HVSn_oN4G0iuT($& z)?&wjb)SbTU889Y3z%`@!ssra;$!C^=bdQYvB|-fUrXg6aryG4ej*+_?j;^SYE*4E zE)~)3Jh+|{%oos~{`BGzJ{IyaP$`WfdS<5G=tdVPQ>8t&1ZxCKr!mu<}s zl;C_2V~zw{f(uXxZ9h;BS^a}(>DUmF;0=#)sF#y-ajdP~b$@hm!10ba`q(tiDI=i_ zt<9zqb_b-zP%bt1G)T=8$a_zGRToS_pZI`Be~)tFho z;K>i6=eF&W;v*|c4LZTGp7BG6zwDQN!S)+}<8Rn*WNqisSU$~kKaHbW;c2F|cIV`K za)!fxN3+>24QR}T>eH5%cjHJInO$=972Ea8r@hWMw5VuhDmpnxIq6nda$5@10K`B$ zzo%UyZO$X4jLmg{For=aynyzTb9{L5#*JJ6zi#{5ulefj&h1;eFM3EJi%^q=d18wsPnBA1{&IFt!a#&=cZ^w`I(D~Wb1ypUH~-s&4VBMKtg;rjkVI{EZ*b} zR%-QWYNPVKcph!!M}OI^Mxp&a(UcuKZbucU|Iin0Hxpls?@Tg}V^Z0ahFyKpFUqjw zAi_D=oR=a;>H13i)NEdZ`(e#Q!NjibdxUO+C+U?-;Vn9J5}g{7pzN!`OuR_8?m*J+ zfWluBj6Hg{crrP(z0Kms=tEC&;D@#PKmli=cF+CEzgS)!!t zD~fv`N-m6TWp^0a6#W4QHs8&_0Q-Q3h~Luov2T9Y0!Uqxu7GK>GLI2RD|YMw>{#q5 z*ixRwrz~Qly$+gO*!kEkCg+nwt^qDw;BOKree?*ul>_w80&NTc;K&YslwCH4)|&y) z@EdwA#wW}ftHxU5)E;?OyvU>qjSqr3c?H;#6E65}^6SZI_mlScOXs*3YFF>Q?0-u( zrkG03IQc(+;rwmR&wb^D*+|NiaU|HOCr zf2BNS@-m!>$=qXhzQ;~aG-Eg>7(ct=V!HZO zfKs6EDI5p`Yh2m3UyHWN5$Fq49@3-_ZL{sHA_8n+L>9)ZmL{(<$y4dhUvc!w&r+_I zR*Qy|{?g~vOKQOqu^*`&N7gNJAK-@Zm;LfzzWu^q@HyLaFFd#TS3?|Q=!<~dF>kBA zO6}0SWz%sHNfC|Q^!b&5FG`^5h2Z4HKOdT$^4K#M?N2`OL@tQ$+TRMU9MXTD##ph# znz4mX4#t)NlSRl*kTq8q9O8{^=XPEpBgy$k=_$MDIluCBC$ZtvJg3e1h4TkFD&uYK zBn6Bo1(Fb%li~WwtCX{Tonxc!1z*WYErgVvwK{)gs19ES5G`<8Xs9r@r~JTfoH zB`W9zS?4W2vMxCqUavu?58wfH$RD)s6M|D{<~aMPd}#3LSL$VB&2iVy6oacDWwn*| zn3je;Uzny3;P{H%s5&RKyDJJT$u*X;cUPOM@5rwHSDl;9k-`^riNW*o z>obse1#KV4BK@9y3-EZQe%s66Yj76MIk0BRkqmHvr_Ermq&Z9}X-B>jEQy~*#4$qF zBp+nervPI&v>qrK#L9L8mfi`*z`jy{p?h4ONJU=1)h`EM)U-GVQjcAI0iof`gDNpl zG0}jLRR)_eW?bwX@Ru(d$VER4#w8kG>7Ip*LeqaJ}Yr3`JqhZFqSXSsl5u{pP245F4u{8iV7A9~O`%EXU8 z7nKOuy~OIlAG@*14^=rEaGjX>4jMn|K#a^!`tEl=RCpi<>ATx|-t(UA3xCNkO$uI$ zzsuW~e9;$gpYz$D-S6_QzG06%tQWqq2iKg@P9wa@wsQ2IU-2~LHNTN^gOp0!kr*x#XVjIj$k_2@7bJ9P{7> z;qgNkdFBq2BJzyIeglqqUWWmkb)57M*pUI^aex5>t4(EN(_nQ_x}x#DY>e!lXXz>K zYX$d(MUOm~>jFB=+fY^v*2=DUOK-nuFIlY&jrmNY@gmz3#E})9Q44*2>evG{Z1$bD zIT?o1cuP0tv@6>f+5ajN+LCpyH{Qa^LF1*L5iTikLc?dQIpIVqvBK*o=k)1l6I$$s zwEL%ILwiP0Sp3tz!?rK+rAV7P)uQ3Ea*z|7md6gV6*m-kK88p;ykiW&dg_BGGWbC! z=UMbG zt%Im056hm%F61bAL&r3IaQ+0Soideyhd65&7ql-v|HAg*)vMd@`@O$+d-T!Ax10Qe zu|GJ7Xar-EbZ`RB&Aw|7UJcGMjyy%~(C6OJQ_(iD5h+~eA-|L1%@3nledxTxAM(`u zFwuV?1Y*LDviP=zCud2_u=j>GvF!D33(36^lM@5Bi5t9ET_GWvV`uQ@6n=OHcCyj& zL!NaUJ25df+$X~4(PEB;{D9&&e8bmo4_>?4Cz&GSO$KdYv;A9OE<6|;I)Ug3$cIk+=U#2uWXM$ z{=|0S;w6uv4#8NejgE6orJeah44tb1#}|?0BgcG>xdr@DXR}DbtHri?U7$JVLTKiI zS%p9HfWO#F>3LiHkTYm%cTCVDm)-vcBOw8j<9>QujW!P#O5Ly&1xax4g5(V=OmvPLzr z!Q=9u7cJU-!f*B;ZDTye^G2GUYXaqGSXI zAur=AMg918(H3e4c}y-@#2iM6r=7wIp0WjEagjqi#Qu2H%iH(=!1r%I@DF})`{5t{ zk?jY5;0LxJ{K0>qe|+=?M}*TJ(@n|AsJs$5a4m-J!-|!ihK*3iz`EI@97t@f1x?xI z(;N^@czLhfdJ!&;YVnVK>|?c&Hji~9b1Nq}96+z;go+=E>g=d3;}2j)e}{H~1?dpW zY|JD5prVA&4{vcQ{VRUeuiF05ANqsa@BKZ$d;9V)`_kxhp%||q+QA507Cgpd092NN zL9y!mLNx+u6QW_JO=>uf@rXM_E_m+Vy{+|2moIJ)KA4mC9DIqdd1>K*Mb0?kht!xF z4?m7|F}XAA_?cJ?Ep`U8-+<#njQEFx3@R!Ymqx!J3AFRp#!h@C=!t5rDJ6VmM5o8~Th(rFw)%)wOBDpT^r`wE!Y@ujnkEOxA~VWLL2qjZ^dT-Wjkbb#inX=m`;8phNTGrrWNizq zEwp=bSxdw|v5uSFU7(LF*NzMk8!4T)jW2SU=S#I>St}q|$Rivi=~MPi*5$~dzuy>1 zeK9-Mh1CDqcYf#gkN?R($;s@KyL|UsRTXL~+v=h3{_7sk5V`YT>J@JJBDROna~gFqWzrFopX7s9oH-0I`5UuD+|Ax+j? zVPco)wzd9So%C~o*nPM(UUj7uNcBTpSpq7HRCG_|0CL!a4r4Kw=SrMuGmlgFb?8ri z*Qad1`8WNh?YU>4O&;#TjMUN2$r%^U*l_Moe|pRsIO4+cNg>9C4Z@pcJ3jw(*M)BR3{09qfGVK29j(E3XdEq5Fbc?QbdgDWYc1rhO#siKO_c$3fbwa+oG#_4eo>Wq^LP8-kolN17mwl z3=aM?6BT0uRE~1g9fjiPr%hSd+{(7A)CCJMz+EazHydZ2LaB<6|U% zQxkF3mTY8Hg;)v`+k-2M#X-y&8D!lLEYLq}*4KXVH#wNrh|f;q7WB5* zPiP06C-6ha*m4Ju$DwZCx$P%L7cO1&dsp842=EslJkoW}n-9^c!5!DmVH(gRM(%dg zJI0jnw=oY$V~3a=5=!Ghj=#Y0WHJoDFO?IT6+dL|;@-P+ce~3ku5v;H-_jpQd;k02 zuWx>(5Zf!qSl<`&6f$T2QsQ0ODkmUF><}4&5*GO6O<~#t@(Meu__Er%^Jv+<4|dt+ z20!fs^?mZtIq+I^RJzc<9civXv2ps&AtsQiuLb3WF#6azumg>$g>n{iVPBm$$$8m;TcB*keybrgHs0D*hsvcd)!fEGtewflB@H z0R^g83em@vzgLHGwg40K`3S4Mi)J%<0mnRjXHBaCKtrJ?afdm6+&>yy%}7~sra@QQ zHoHj2Iv2nF;lEWj2r9t)Rp05rmSXDyW& zILZLpZGN%c{F0a2RebPCQz4zxuK`sEFFi)}^QlEI&~9OWQZMTP=$%}c{mNhQEB*T+ zE`)jF>7=K|VB2=-^5q;$`;?XOTI2TwodXM$m;xMmfxSbaJ1<(e(RlsVEpK4+Gz!kR zA;R~8>9!ZZyB}=SjucJJF@g>XaGL8SYx+_XZ@f+@5H%1qwF3Y-we8r%E{c#d!p=EZ zB_*%Pe{!TJ%^}<@YKGS61CFEqDc}G#`)2w6h2qEod)gL2$Qv*1W8>2INv(b(+x|8e ze%ij`i4UKEBo>|)31E7$TWh3tC*J<5d90d<#6YDOc1G4FL~?5c5sj>46rb$B$TV~A zQ<%3O)X*xLcX8x_{SoIy*<*lMUwyKo^yc;;YdytWvJb$LP(E8!h|8GC+w=iBV~8L7 zSY1k+$aCyLhIX_w$Cy7|qlQdh9iIVoN1ji+8+*ye`ZYKUWY%gQ=ou92WYGZ=FWEK) z$N;btxyE2Bh@!JlyWEXvm_d<0sk8PVP>=XxOX)x_n%Kw|*ol@QWYL=Vv8OCLK{!aO z#wJBxHp~#-?lBa6g%j6Ucw2CB~mq5p~L zVx(a?d^+eww7Da$5T~>qWQdJ7btiw)z8Pl|>iHUR77nF$zz zzsz{9IIUbc5<_!;h9c3%9 z9_4Pkw8o1pV}MU$3=MikgytQejC@!X#35&i>)lU322X~K3q*l)(MC-}S&A?(g__8V>r zz3gL+-}}AayZy=k>`&za_|dEz%yIsBj8G#2*4^@=e96nqshUs!r2 zbZ!vu$I<;)!pE^aJ{>DvOdiOozL9a`sPYT|1KK}pQy7!hP97rLzd zeLv7SHZpdporCgU+Ma**ne7XH=`Y>B;TwLNe}TgjHUKtR+gbJeG#)Fu2P4IpuFAa3) zM|;S$?*(|Q?}%kxAG^?<=M4yge2=N>L+Ds8_ie2l*z=|8&0-!Y4#lbwQe#YE}H+{&SU z*mEDRJ~U@vWSnczmhXv?$FN!Jjc;gx`v7TRFvx{va-MgEBA~sN&f_VeukY2f!R&tH z#SQxq(WRh{KlOXO5s%FkkLzV*s~lgt1aCf_cf^68(0SQJF1GZKzB;O@$0PapZ$3h1 zI3feyV;}|+oBYr(FdoogQR69jCx?z@&Mq?@M^#e zNrp&plEerwaG_D4F)=#$rAbeLCY@%8rvnDG6TJ$Hau(KIoyFrss3)l>$naXPPszrm zw$IpHjM1R1_-O31C$RzgF(`oD5U}sWLU8(^GBgUbk(H3XfZIxKJ~DAj8GYo27=7Moud6 zS{dKdXN4*pIS^s*#u9KCD{WC}WF@ zfpucKU`ZFIe^926Hjkj8NQA#+7MS+~n9Bo=`Mb;9XV?Q~ct@L&9%L?{S4`_}!o-c< zUKZ6&^%;|@jy)U1zbrs%dm4jayM55NbPBP+%)DJR=Oputbu=UCd|rOtoPpJsR>ZYR z?4*X@KA$+Aw5|1G?8cq4XFW8AQ_Q6)cZOD7Z&m&+C|VM<5F?w2WYR>?b-+AkWypn8X<_DFwf;T=`|Rb*SGNy+=)>E8{KvmTn>^Kl z885;#7|qDf(r0l6g66sbjXB5oB973{9yGl=_cOs-J6sq+fYjjZ)8f#Qk7;WgQUDF6 zS6wj%YkxQuFY*BBqQ`w|m4ajDxF;)|*cuWJBsH}0r~cRkfBKncwl{s^8@F%$o!@Hs zT$~v{zVh;-D9W@nwfyI8-zM*pN3Rvq^`Wq5^|YC6U~TjLVsQI**k9+z)oi4f>tB#4=HV#sS88XHpG*yjj&@sPqC#XkDiu3XF5 zWWFahwAlAq_doCRK5zSyFaF}~si&UW*8}YK_BN8$=LgL2fAl@>l~Z!sXMhg8Vt+7V z6kh?|-?;gEV|(wr-@QHj;KTcxqR-f>#In&iEF}b|A1fvp&7(ptHq_{+FZMb3oa3x{ zQ)8VMrO@vdZ!$p7yd%TP5*LCbiHf*n^muauHR^|w{bl7+dFc@d;pDqevV!u35G5hc zc?;xGT6SmPEaay70r0(qkG{YoJFSx|^ue-O%+Rz;PIh}?CXo6frs`3M&pt%Vb)yzk zF~7MOY!1MGn>&r&JGO%^U%OptG%D*tFuu?z z2I)Ro7(=6Jtl;XVNUNNERyGzrX<6wy$r4w0B$~|wvYzM=zY7_6q~K?xs>W+y@70$# zU~Xn7Tsc4W0o~@yyry8v!t1#BTSGq})B^41w+H5-htU6k#cq8zRu+<8I&y&VZ<07b z%4!@oe2=ZEKu+VjO7qov`mmT(OFmUoUwKt3PzbTPU3mx>FpRx^^`Oem)&PV=i-U~pF` zk-p!~9Qn|PKfGPIcu~Lgow%Ir$Q9goM8Gq9l3U^iRM~YGAiebILs|!WD=79oN&y=Q zFmmjB=&$ji>iV(b(&<5FY$pa~vzdq^Wv9h!W9Z3~G0*;iZf(;%*@f&l1Zk|uj>S=d zURw}3aSwg^1--dxY;ICYQUOl3v0)=T#xQSVpwOf}ujNaz;M$dhY!I-?VT){SVUtp+ zimL(yX}m#M_k!pi+G>yJazzo40UvpdE1b=u1tK+mu{}m6CIpQwG)>S!Wkz#sAh+WO zn&3_(Vnx2z{>%Eyyk&myi|V&;-`xJlAN?cSPyN(~w#OcOjG@~u@Cjscr~ho06{;26 zn*1wH z!rvb817sI3oZtSyANc*-o8J6pze?i%f}hmLaZya0$8o#<0R|zqY!`4!Jj9Tgx??zh zyoiGs0mq+?1fbX{ZL9*cUi-T4x^ULb?AOCMOG~>kwO%*ch!w#1da|r1=(W3I0$&9c z$ZBSz-Le9e7fm1OC;K}(+MRIegP(fmSiz&lckU(^q1}!Aojdoo_kG>_wzs_HE!(rt zJ=Z6~P#Yh;0XBr#qYo>}pApdcxPXN+;5)QzdQ1$!8(DohpCl7X>Y3xtFQ_BC^lRK&oyc?ZWSx(W5pfGL zJB?se+WF**ij8%cR@jYv_q{+nZ2M#v%J3FJ{aRQ#;9P8{rP_Tj2uh#VF-jme#d6Ku zb?l6e_Ev5tXFwfPmaq&BS?I_nkIExFIa>g6%!rQMvfVcGltz8{FAO2*L0boV=4|vs zJ{$jQu;3hdF?D->nlS4bk(E3u6I!xuS+=J^dvx8IO9;$Pv}9A(oRg#|(}ho(AOuF% z*X#s9_s7t@OFOg^3M+7+2bQeiCoUE)+NBTVpwkyZi$1j2+-0pwZ>+I19f4+B3Cy5d zZ;B4jNj$GArs%Ws`bvA*K*Y@~M(K$$HLsiiubrzqrV=c0+6;dswMz97)Yh=t8R&fH ziT0^*@hcwaBFY727U>)yIeE#bX%jH&kx8R;{Ml~5MzB1a%$N4T;}d-j^upf}nL7Mw zX)3kzNJ_WXv0+M&pV*P}lozkR;9n%6&+^9I>*_*yX}faiqG^7al9%di`;oORm4h~q z)z?Dk9m-v+5F(L7Azn`s?ydzL8!gOD`==YUXPj4o6$8?68$Y^Ao0Iik+_G==?-yhd zpZTnP6!3NT4u2o9`TgX}SFd;?gB0JjQ$OK$0d0)DtB)OSl-%8Z^aCF-r!3Ar`A3ev z#E{+xv_rwh$PgAfveBVKfrD<{SC&DgO>yKfv+vjG`^c_+a>=T1VGPI-ItrCmgAv9L zGXk8kI?cZbP7F(S^lVa>-fewl8}eNIYN9@oS_eaL`ryHBe0jqGQEaG!y;T+s`{6K| zj-bhGQYr^PWNaD(Iq*L~iD78!q~>L@^AaewAvFCBg)MSBpQdzWL#?mO@ z9lzCezKEpo1_e?xF1;y5KchE1EG*gHoElpp7+>8M$3~lxLny7hy$Qnbqi?N&R*8@O zV~eWP5!YrcP?-JUN3BoWI`TmxpirI|QBEo?vG_;tSe~ zFFe0}-EaNc?Q?&@FZA!_;A7H%17N&j`{IR5sqh#Z#30_vDG-Q^Xz`W^N2HthHa5u-TOBXL~Z+qL@a-p7M7_moi zkBg*$?ld$hPMS1RQ@Zn4hIs4`D4V56o6=l&KNx_n-9!*vY3h+xoqRw?fC+F8S@>lV zE5{9*`;GB{rqM(;aq)?tdm@Z712apqv9HvnK+uP;J-DTc-L~2epr4ld%&`$MH;}+n zdhB9mbX_oqp&8c_luiK$n&(1m#TMjzYvrSK#wO=C?xRVd{Rl+W{?MMdJhpM%B?ff^ z3qe0DWS!R`vA>${wi?KirzYQaW@5olV2O0Dq|Le#BC^JiMsrZUdMQ-e%iCkd(uoL# z*+hR(*0dtEN8!SkeCPudD*Dn(m{H3X1H0I3a37FW!Q3q*@BM_7#FET486A-mH0hIM zC;b?5pqZ%4Z~#2?l1levMl2Avor!v8!IzKClU+gCu}fU$md9CFJmaGR0WO}#zz~tMk14J} zaZK|}{@j~#5Iditri7>06-yL&q2bqQ12xsV?rU+s#YqXW>BRcgQ!bQV&egK=x+ETv zte4cZae*@)Iqu7*G1l)MPYNeVm9OlYqWuJuNQ2XdS-`pYpAR*IXX8mmbhxm9Z;nDr zSr+-Okcf5?KLW;0jxKBuKk`V&%7Xv!kl}ydj5|$EazaCwrBj(G8KL9UTm$N)m`j7H zK6lqS>9fC@Sh-;i(5$Sn!5@=dTm#5MAKxs`&YuWgyl^>q!C&siRN1Y0{*zx3IVz5>)IOg=vi7F={EtLzCc*P@! zEGAUPKQv?pWKy>RR-Ux0p3Pl$@$LVv$JjPr`9p7e)jP5H)cw@8JTFKRy%hZ7Vt146 zq)!@r1a_Q^tvxeV*eA)6?eZ%=9^wnvH*VkbyQTC8xs@Gr%!yJ?!XCbQb^FWz^)!tKIqc3owE3t-(_PH7IRbD&|Paf(R^tmypa4J9Q*uCqK2CsxekODn~WMymhg3s z^L))B(DZa3Kl{ux+n0XHmu$cGfB9>(e%-9;jERpV#vnHq$?yg51!ir=3Hy8G`r|$L z&vw@GGr3Qf_-^f`i~TDl{`Tt9r3?F~oGS+Uh+j(gv6HRlqy1L{IXhp!xIcn%K^IQU zt|w{Rx2j^3W3Mw7rPw52<~(h*T^d8<4_UMzk@Y5W^urjT1?81ked;Ow!Y&Mc!$N!d zs6NK&y{IcMefjqJpZ^QC=Q1uALgywd`#yiCgwo9$w>)pq7q*VD6EIFt zp!G!`UI}!rI*8bh$dfD1jqcpKwSB_tUguLycfDypvJvFw!##iFLQ2Z=Gk|I3r?@_X zhe4;EM&CvuD_bG)tLXB~j7 z-|>(+TQz%RPENpn!`czRZuA;Stj=*xE79o5>d6`VFy)dZ z+2{%C3?)125&^K~fFs|*Jx#XI$_|`pE56c7UypFKx%jIF+#^rA`Yl=qy`zNzc7As1 zMIT1N9rq-=+jX&{A3c$j?at602nEc!L$5sQ3l_XEksZ5>whHZ$Mj+6*P-}i)1sYQI z(W4Cso5oOEkm0*1xl`6BzzK?D%wCf#V(82R^Dt96zb3x`-*0{K#TPez zMUtpkNbF7)Y%W5G^${+DS$xeomZR&L*SRuIHw>_ZnuR(b&0zH8XLLWUw0GbfWEGd@SVr~NE6C;XBLg}9_) zA9{)gX-^#c7=cIDeFCW69{5IY)S9!EvE*iK@+z?${q222rn=>`pQsUN&Sjy4P3!L4 zowLPHva{ZW1a;+&wE_%)UVWhU#YbRogH!0!*qv|{+G7q8OkXM@ME@5aU{VE0<1&E_ zbY{8f23kc^V{aP7PYlu_G=4_0MCR=S?vso?_uR4@28eTf1RlI{W&432_y^l}eb;yU z-`dQ3=CNNNiI2-yE;~QCF;pN%su*y%=oh2Fi}|5*B|k3U+rHc(@P<)fX^pX5?Gw9jppO4>{`aSr(_^$QpBR{IiczylXfBkm((#7q@tv;5X zENb`Cg^MwT?;JMHAIIT7fV^@_FrceVy>PtI7cgxVufn$7ym@PT=R4oIJ^AF5-h^6O z0CR)mUDK9LkUgFpw{%;Rf$$uMML;P9-{uE6(t@cB)K+b?-XL>Uzj+>CW!^hG_L>Hlv4Fw!^Dz=VUgD zm1iBs{q~@FVZ7vIRRX}(Yw$`qN3zW`6Kj%3*4&{0XeNCnk(s;70`#VhD1s?tVPIN2 z5xX>|>~w&3X)BDG8^XS$tat;RJe^3wu9&z^L|=s^pPE>e4^DgH>Z>wc{Ln#`dI0fM zNOs271WhOD9N;N#D^gkUi5dUuALLLKN-qJMr(If_EGR)-SyF7DVqH6iFv@B`4^nA1 z*@ku@2R(3Jr$vVriyIOK7J94ON&eUd#@t68IcBOQu&NlxMoYx4P;;k%gWa(l#!Pi~8 zu@RxXy8t_%f^fpt?xpPrP7+*94LdX9I^v0 zF0!jlL4;qtzi{b7|Mo3ZbIp7X&i8;n_|reN{n7vEk7Yl(K`<#}hQ16&z*7hYI5lkMW~QJn_X7JUl6N?90*4I%c|F9s22bk6oRiv`plf!||FP z>^eu?vAx6ic8L_mR&;6w`4k;4ajgrr#yFC9)*_qYs9eZJ?6s>`)gYH^EYwW@_=J*A z<3II1@7;dmZ}?4qSDTAZkHd=c<8ha~pzbBfzX=d!BgLM1ON?v20gOQ}y0-1-{rsP| zUAcV4_&YWnU$}_BuwA=$b#g!_v2p58e`JVu6t#_@!mY+1m6(Q74k9uXSn~`%qaY(M zj>V$NbIjzp+Zzm}Ek4CQrZncnCT=4zM!=l=G((u35?x0c`DG)8ap*C$03Fu8jec*K zjD6Rav1dVng{yOf-svx|+M-PjR+}e?)Wlljhkip620Kd}C~;XJhNh!A)>hi9KxmAW z86>czffId?Z6`%)`h9|hFWHkm&ODEyJv8Rnt{&MX3alTZtNj$-M_;m+vC5d&$T&vI zmd_I}?gwc}+TqmD)NAkx$Z@BM>&4oXW8z&Xf@k8NPHvG~JJQHm3J#n$A`{srp9>sz zo(0&ZhPeh$!O+tRewwI@wc5wJkGQPKv(KSrD{xvkg2P{n-v~3Y?wg(#Wc#QrqLoFu z{My|Y4Dv@`%gCla&Q9v%PL;x2yeGqZe^BB{`b`F4AaIyu;qJwA48W=HND3y*r*0m42G_lI_kP{1OWXq{IfzG|-0$NSXT7 z7x6BbgReo-hu}2PG_z@pYU4}29%W_`z@B5xqm2mX!W8+X?;~^IOD;^Nf;TIi6TQpr z4?TsiNM2kxbI?a(+zb6xX?hx95nA&bJ@kWmhm_dz;sE3{34{Ofy>jK!cIDzFAG<^T zoOjD(_kn%_0(j8b3vCR zCtvrtb3-4=2Q~4MyS{U=>=>mH9)AaOGd6zY$9~i~$qU{~iHW|TVg;g9RaJ{pOjC~UG>S}Ju+IYvKf7Kn=omS%4?67w?NtKA zqA@6W*Kit>?ifSy(jcBr zjK=Ok9y>j_>sY$D)xaI+$k-a#^#jDJ7Pcf1|L7w#aU!=4{PHqUdD&MA z8)%EJ4mKOFC%lX=Vo2yOc?lU=Ot`+KW_{z=;#qV4lRx< zzi?eU$O4ATXq?0-y6AUW5ziq7ZNeIH~Y~qfH*D10&vW6Sr(? z`Xeb2z0~frdFxwysUaoK{t7yFGyCz&OzsgWqH-s`U%Y;M z`^vBU%3KV;dwbz|{yTVFWzAbpIzd=B23`Rus1(5I88I4X^_b5c2X1miK5_FT22XK( z+NZv^Ph|v*6mty##cWnC;ZgwBOK5-!=|AmN0?P*H2)L#{#D%#4K9Eov9C>Wc2LPpK z9gSV&;2%G=BT%OgNyT!ib)HlSj(x;A>oa^F>1Qmlk1qu)ZNEc1(F6F#WZI|mJ8Y~x zjGcgT<{;1xpLCQ_z`8TMarJzR*%6({!hv>fd^5+JsfdL}SD>^kn6W{b4e#WU^}ugwM_aS4i!F}LNBl+th zi%$}pOp@cLC+_O;z#(5_(E|i7lPAFkyCFb2vAxo-VPQ+@P z;jGW?NSN9Z|><|KpvxaDR3G3ocDJ1=4_g7}ADok29Zn%FNLppk=E zn36-!VMojgVd77j^)C=4!8X6B(vBEEHW36Btoc2$h;WePF-A0eOe=k6!Q(`L?|?o0 z&_hwiIA!`rD|V$)2f;c9rEwl4MhwviTCLLYc7ezILg&QlsgHha`|E$>zuW%m|NZ~A z{lriF?Ad(t|L-c!H-y*S?uBqGIU-+DB$yTU$=#xCmyS8(R@@$TL2w2X5ZH znUff@n^(q*{|aUfdQ-rDAm7-r`9N}o4{*QV7u%OFUDt1kXcKif;!2c8Txo*WeKvHDcA)gyYHVS80an{D-+g(zedneZ0Nljs zJ^;60k>C@p@A*If7u)~vKmM)l(Z?T^!>hj@%$W7US9i{3f?=OXbKUrfU-n5ZwEP-I z3g1t&W*uS;iLUa80&UrOfUhG!pS~Z#E*4Eqjys32&F?0#&XJe6(~iCpm;Mg+I2@9{}*hTiYsIe^U>`!zZB_Y&^i z$r^Qi`^bksy#40i_#3t_{Gxw%dp>Pv=klq4{Im~{2&DfriX{6IJVmwd*x295@G=j4 zk2p4yqxZl6{oCLATYqc&$)EaZA8+SE&V_ro&BZqREKNFbvbB6cQJgxl@KvHjnbumv zfFQ==;Hpr4%F1Ky^2)?HsAUrb+s2PiNU`J1fhC$0urzVZyK_6oaEBv;5L5YSHshZN z`Oz`>UbG~f=93@5q&(m+MKh0_e*rH{B76JZ?d{6d%l=r|om)4z8#izGLs{Om44-~? zy^bAXR(k>jf)YQ!(#m{X;6?m^T5IQ43VWcmIj-FCuMOY+j(2T0Z{JGylJV&C$acpX zE%u6KgV<*-jIHCmUwEr*+?Qx{6e+|P3&E0aY-v4-o8ztArO&wMReQrn$DM#Yg~2&z zWC@9jAHUa(bgBm)xS+qa4;Qcj-wfBy>`!W@t!M{R+1aF0Lfr3wn*-?Rr=W-$W3Aoj zo2J>HtTjHv((L;GwW-Ui9R2Q1ruMH;%wzg$$!Z+LxyQ&nobxoGU)#fGWC=Hw#{$`* zD@R--gFX9#F!7N`d{am6=u7{&Yz*k4Y8wa1jXlBzj`zHzHip=Y?Cc_yTXBV6Kg8f- zUm9%fRf*h@k7ks?inZ@T$Q01{j=TO>Qxg z%&W|m^chIy86Ze&aEB}%({1g5y=B{p+Qw;e9AJDQQXTM4fMsLXfw25*YiPpA=*#I` z+2h1GQ%65Y``*?rz^qbf*#s&Jl$xz7i++;T?a0y~M|klhG<0KU0o{SVWI{uVZ);#= zHRTDIR_XxQ1sm=$Ph#q)KJB3g)!J3Z9lAD<>zG!DEfFTD<9++eH?lO0$4^D-|L?!O zeb4uN&-PFL**~5Yx3DR0}frX8$9S|vR#gTe%XPemR zOG8I;x0GgxqazHTvDsrBP>h0XYWaxljLO#^WQ7qdeiTDjc6BtFL0T#t^Vf+3x)f=t z=g@9xj9r5;!oK3%Qhw#WP&{(j*!Q6oTZ#gu@3KP2%QE`qbvB@Hy~o>f1~izMm}fg^ zEu}tpT$t=r98cWNuLtR;nxf7OYtzI$OXc_4mcMk+{nU|b+^5y)}OCtULS zbARr?+`jv}zkB=h|JT2;{mK9IKi&S`-~D^J`0EdJ6>8HPAK(c_t1~Cp@ftq#(i)?i z386@2Mpm#Yt`2=^(o3JQKjoh`a^RKaHYG7|0adR{II@moK`io&#qH#^IqJCVC(%l! zkCU4oe=}~7r%(7~&3*CujqS5P=X19&`I0Z*p8nWV#^5K)k>wYg*{AriMO2w%>pxD3 zonuQsWjw?i+_|VPs6!7lH=!+^yt$#vcY&|w*v$vQ%16$XjPXu9kW3*#1=3XCbs~exIhgmN;?om4M^)W!KT{&0wkZy6pF7h=UD@Kasv^U70ebB4LSLb&wb#;k z2e8RYQ3etiek%9n8G2M?z*btXR3)l9m97fr9}r z+MHznPyf^3*`9mu+3m5%AKM;%^s&f4u>Fny$A7oooP*xIgWVqd0@%dfTJZI8vI}?t zkvAuIJkH15>4LgG*-Af+8(K1kNnWYJAAj8w+Y?Vb;ioX3Od%9|x98+_9hA8^=B_>c z*&bIpJB8#VDhfzVnG%V<+a+sXAsS=xj|r{VE_6IwKWLaJ=vE6aNm+{r< z2q+XlkNBaS^1$3ucK8aUZOi7eQTZc4S^dJM6m+O%w$$42;nF+lfKN^YH%CeWs~#|(8RrGY4WQNB zI^?`y$ZTJBz9hHfQ#3%{DfQd=pdyXxuTO15Vtz0EU9Q$cAARxr`f&jG)d(EK*zaMG zS1wX6U%rwHBi5(zMsA4{m&egy&pz|)_SUz&W&1;a@DJuf^pZF1xQWL1ecd0?GOo^t zGqHo`g&e)zVfsjh(Sn!5m}}QZKKj)5eLwL1Sv#+JL4~cq`q%#2_S91!+rJ~u3)|*F zLz6>rL5Tpg#>ISqUYV1evY`=SNzfvT*5nYe6(J~{w2D&n$9I~SU%`43_2eBIZ5-S(z8ykWcX zB7a>Kc0}B7h$#dfGu@A^0plNgd{#axlNb7DOI=Jbr@1)Z=_#yf9MeDJGe6xM7R`~` z#)i?U^rsrZX@jbD!zz9j&GO&UI<^ayS!1$ft4mxls_|$@ zX3m{r?y-Wn()QdVF!_z3a$dwbmpB*clV}aLeJCK?hP5ag=!4RSId@y54z6D&;SZ5u9rmKssYIAZ&ygcUo!2FM`q*W*1#LyGq;_jBj?V~ic&*elK zD0b)}jtyGavy{^zbv!4&kU`-ui~2~T3+?EcyFi4IJI5m$WOP!>~M$gSg^=8VSAxf<7rX(=urFMK`=yY)J_o|OMCYD=Qe*-jG;s( z7u~mS_5U$@qRk_c?1xd&Jh3Iyo~(3Cda|O3c6-OLaqwyU?Sij)j0vtgPjbXSRleXY?fU9h38pU*LB~gK^@YIbQB4dx zDYbDicT19wa36C+cIku;Pd>2f>X=jQQP{`GK4YT9l+FXeabGsZhj`_fQp&dqv_HgZ zjIpymg{*%RN*Ac}Hf=)_r=EgCl3kmniT=!#bftuHOy4m=o3K zxBtT*{g1Yf<^t*3gAck!)K_80jdwxtu~RDjVT^&+i_WP(W#{{t2I}ai9e-5H;v?lW zzG=_@i}JD!HoE4J0;K^iJTe{z z{Gl16xu>p}@+lmT_=Jq_-TwRk!N0$K;+x-+wJ{fY5hDMWazV=Y8aF1QxFW<90s4q9 zdame7bu{K_MY#_u7efCog`P`=wZP#z!*xvNU zH*H`4^9lrd?l3OKm^tdF#y$!wD^akv z5+jepckbGcjM=CETc5Gr%Q$17qPgh5#Ms1-@_Fe$HjLc9#5nxvmmwMB@Q`$3qmeM> z!F6PVl};=k6T>d0nFH#R{MG8SPd~Fgoq5F=@Rd(48Agj5dt-G_}rv(F zktlKyf!Kv3r3PH=>vI-DwYtUsdgRJaKGJ6$S0K75uvju<)*>_gi;%ein;Jn?5XhT@ z$#RN+4ryjfQ{gTBbLlS^ADrRzT{?d3=sPeq3Wd zxX1>7V=*%LPn6?3*c>zq!4n65J;YbjS^V1SO)oDuVkN)ttQ$PBnKkA7qeWYBz(jO9PPH>=Skd~mH7(=yR!4zD0e3Ji# zuW1%SByD-2ELUR}J;q+#^`>n0lWd&Jd(IeeV#?O}1r0v+uD|?YUv$QY zh`Rr?AFjB}z?i2tzk86x+kP%sxq`N2p}GGeOFWV*$Ch?AMhCl8B`twn2XGx?{|L{0 z1=_@el%GP_1^P{{lEr&`inT5Z8_R|4u$+MZsXz6d+YkQ3AKV^!&E>yYf{iS)d(AH=1Aj2?avqK#jQWW{vVj8;~|r zoZ|)ZtaE&4__=4F-TuAb_Kn+Tf9@~XUgVL{yl(TIR{SR?tX9kg*M59!f2~y^#h4cd z0ecZ*_XlKfn3`M=XPC%7_uO;a0~eT&n5(@fo_u2agirW{*t?6N#Bgi7b@!Hd-hz3f zNNHa!P@In)-!%s&K>OQVf+q$<;e}=$NHj*gtfSnTzJ)e6m;Kf$Fujt$60n*A{}>`&^k z8X67yik0BBrRlx#V2iiD7Y&ixT6FW2V)RwPw1u0GGbPGM;kb${^UDckS@9xxpwl8O zayfGF&CU4Ne#xCdEI{=j(Y{j<077oQF^3#@jdcFN8QIA3B381x$RO=k?e|6od5*ov zKJZfabU+tbo9wT&;`D(z?N}hhScU2mNG#)<7=ZSd0Bw}_8oUCM(|xE-;wgd7+9q~r zWK*o8o(gR-%l)zz+Z1*#NK88rWIN~ur{n0SM7X<`M5LG7K#^XAP@rhsb|;qP9XO%s zPPF7saR9w=06r3%_&|?TJuVSlmF7m2~tPd`dN1AS1*pR>sI`19~OeK ziK7}218axFcAEIrPi0!m-ecJHk(G8LQCOV$WY5^bLhu_|;IZe-*F zU(kbf?-!)e9EbK6d@6xO*+%2?KsfS3Y%Ec7iH*GvVMe80C3P=0E-h&9$&tAX}-hj0w`zKsZsn^ z_Y^m>9xm0PW-ed7ay1v#d~$^hObW7{E7-kx{nmCPh5g7Mqq%c;`#EoYYc6)Pu-cJW zi+oR_$Pb@T_khjcw)fDe zc3;2_evmuL9&Ic***NM`_I(nPX2`+hQGfBn2~22>^Jq7)CcP!Hhkd%VQW-PjoxZv~ z1tY*4cI7C_;J=^Xbgm+?beV}%iR(ajo=hG=%Zh&}j0H_j2zEQ|@A6r753l0bQ9o64 z+qG$hxW)`x`wMZ=3u}(9+?ZRG)u$iOYmf43a3WV0J#8GI_5mWPF;BGX$eOBgj+88T zDWgxcVs84$*F)E?Y=7x5{>AOD{FT45J@y#Cn$CVT`{ODBEL&n2O2=bjXl(10~9N@TjqQ!#;0~@#!q5F#xNL9_iK9>T5T!GII#alrYD5eLy;SotldkR_fhc&`)o_@>l%I?brXt z-!K=z+~drOlM7LPRiAMn+gRv2SkQi;mf3QOSUG-yADX%m#6P<4o{kxsYD0LqExB zE*sYGUI?zI1sLnvU4R-HVL$KKJm6#d#AQV-e+ zYTDB+zV}P6f7{o8!}j2VS96TH9tJwGOE;B5L4!LFaIEy*eqfzf`RRL5a^VGD-dv3G zgIyfYKjl+CWo}k*?xG`Ysct_|z|L})jdo}Zo!1;M#q(NoAN}eLtgs?u!);y}OI!Ml zeuR2M9~vA+ie~q}WfatDkh*aryLia0R)8jY)`PpR&)8*L7`7!(O;!P|M%MgBR(UzJ zTVqF?PV&%G=#@D@K2&(QAyXnY2f4w%#zFTo=F-m&agad)z7gtl!2FN@{ac zYF_Lgp*#HDcMR;zMLwj_r$pa8pdqihDIgz7_q)=LIXLFAD$SL)49kr&&fjSls=KUN zt7t=NZIllzd3VXQ*ZQS>-mUh$?zusJ;jh6fz^{*((H+__X(>!flDjYJXObDb`3__- zn81vXHdqiKGx$I!o2(AiL3Sz}iIi4Xm2C_PwS=Jf0IX2NmrLZ?*#H&>+O~GPpenim zDT{JhLKkj!WQf&QJ)4?w8~f}GV&d$H+8$V;Hzo+QCB$Xr>I+C)p6mejD3t>mNq4~d z!7e5Kv023vq-m(eIr4d71(1eIO4|PFb7UD)A2$he9fU2pkn5u)S!{-sRYw~%c+sf6 z3K-KWP(0(P%9yGo8+@aiMyH9Jp7b2)0S-1SJ@!E{+L^bjGeY?B$Ng0<;zm%}bs_&! zPI`D0xlL>Ut1rQ#ucru%%0TlXtxB2(kS8_@9rEOJKK;U;Hgkf<4|3^;@!=J|i+V1K z+CL1}IQ_Pb4H`_GR6gpK3sr`Ri{OVJeAw}GZbpwE2tm+S{NBEEYkTI|XJRG?ocQ2z z>nEOkavr1RVnA<^=KGPf@YUFOfm7h|7bZ`A^r^WB&O5$fYZog7g?sVYOj{72{!#5b zjdiyy`;6Y&uVGqA906#vPdS&NFB?J34Z#icWONrO#HjWUboMbWQtt=ERv`xBMT=aQ zkNrI$HpW$)YSkSx0AJ39v`Z;C20AJn@ibaMd3ABKT>#Je6gp!|9P)K=(yd%&Tdz>H zn%C$8Q-Qb!5${fm1x*dXJU~E}z8(faT77|gOc^i_^HL_IwDJmY3p^6qn?NTXuH(`8 z*zbvvi?8#1m#{N+d-&l8x9|PC-?#mlKl5k30KUi%`xs;OPCyP?LuGn3jK;i2G8Hj$ z(QpEU8Jmchuf$hIS<|LvM}k{9IN1&=h!8O!R>cQu8R?%E80zt z*3{$^R-h*GiXGNWW23SAo3dbh>OdSHl*XhpD2ef*^`m`hW3uy*_2|y_v5$Q$7c}qM ze#bX|qrWhG_fGobi~n!uk@duF*L&Pq)rf#gfn^)G@oBS%ZH*+VJ=@)C(3opF5 zec%H>KI8|H@yrJ@@R>nF<{veL2xk9s>~jHjZ_UK%3JJr&4f|cQ>|g^SyBU z*VuqNq46L0{Es)^t#zOG7#oX`VJx~|U~6TYh^d+@dlZmB?hCw=c+b zgQ`5FtQU^fx{<|W>->lH-QfehVDmRt?6hLW05t#X2Memle1yhlh}2S}XkH+sMz_sy z$A5DNfBf4BBu~m!AwbTW1?;T-%=3lm6J9|*mx1R?gu#w17N<{;)9yJ>{b&cfIhnMd z>>#pYn|&?s%GRcR3yX@Zv*u zwsd5)jn3H6X5$dnjv|WP>2HYj(Hh&vLVM(u&D>xnn=)ziV-%Lb4UTZG z6YrFzw#7=HjCO$b5oryO<0=%=?!Z82@*iXmVhRpH{oU6H1z&dEA;!$^O1_9q;}Z*n z=gt?}I*D@Ui3C+?yR>k$+nwKr3r$5&^d&k%sahLD@YP1;3Y`d{x(=*|4F{wQCTKxyFC^JfeK^r^Tf}K=bQlZJ;)~?f5K0N@xp9%DoP5ZuzcDhJ_JO#4 zJW!DtM+!n|16TtzpBR=;$G07nM*fceJn2k>;U;t+@uXINH>O|afOLj{9KwDTsA}yL z#*R_um6-0_y0hK7nTyd}2q?~XaI=2$o!{r5d)77UfBlF518>INzI8k65*G->o;wyc^G?$qKh_b)1511=EjRgB&w8kBC+Jy zd6#u9lPNU5n|vc<{8eA|HQUeow4b*<|NL``a@0`UxYteAKy0&b`g9Tf%nLcb$;7FE z({9F*7`YK)pF-jSm`9)A^~vu{zYvaXLXVxk2zkv3-{onKxdgp@*97T-IQI8NR6sH> z#wktmv8?ZW&aLKVhZaC6(2)sLHghNIiu; z_7__EIj%yW^oCE*%UZgQE`Kv$(8npX9GBoUR_M5)Un$5ZFUYQ6_eKYK*QVu18nW>n z15nu2;8D3hfGb8v=8rZSl(=8x2%mji5#!Wt#p0(^s5ToLzVq^Y zi!^i{q8~34HztUoP8xa90VuD*{g8Q)q|P7$Om*_sqz}!y1L4T*ux4&2;DS@CL)#k| z98@}OCJY6}iUB;l@Yf`D2i1AF$T~Z~hbMh40O)dXUlcvL1(K2kjz+$>xGPy?_UT80%P67#%mb zflf?wq8&+Vna433FqWN$?X)y?ls)Nm!B=X^*wFv-mF0;~eo_GP!(U_o^!4&(PJ-}O z+HSArCic?Iy})7=92Y5mzejiUaK?dFOmYC^mn`9_Z6DA1cOVR{ISR=iT47w}7d+@t zrZ2c$AvCWkjui)~bMr$!_^z+sEe#&C=<%sHkFR0Pv54I(mo9DZdgr@*WD)%TxgfJfA-J+g+KOzT}G%KoILW1Q&idqnbW<-C1!BVap$u{`IedE zJJ9Fhul}QZf`e@QYTuYbpBMmbuUNR|dBJf(J_rNx*t-$H`kK9sKE zjF~sx68e=(7juDjbNlu`{>QfuefX!{fA}sVbJ>%lv3o3ynK>2Eo>ZGi6pF35nkVwU z?6A#ijvYufw^>&lpU^|}+=o2*VmuHmPctdVO3ruzyG{Cuf^Yg9BqE$lb4j8Uy5=kK z*$?7`UR`9)J^`WD4#wlAW4-{ieUE-F)VSC$vHJJ!-tqrsx$yedZ~5l!J)ibz+jIP7 zRod0#WO7azvo>76{$kpp8y=h3iQF1rYP*lF`hn0dUcNXNij)Fu`t;$CeAwSK@OKX& zPCwrM_MhW%5HNq!=jCgsO$_Lj1|*iXhV8jRE|qaDKhP*?(?`Uhrmv2N3a2pu>?6N< z;Xpypx{odFxXvThabOO8@F#zA`;i~{m)np2*pF@>`N&7MJGXB+7E#FXcKn$W{y-eo zVyow7aEPn@HQs&hqSQIc&1L>-2{Olr+js764?X}V3#$B?ug1GM?+Po>Bx-@VQdNp>yLbo^YF`Hi8y|bQBDHvmH_rktoSF0M) z9&z$LX)kE8slVDbL(;HCqc<2__hVzlM(un|Q=3u?{P3F=+2BWNZLE3a`GBvni-1bm zKWQfrW%oHBwOtlL@<8XBKPbj41|<#FDO=4MxmmKr(9$TN?XrP=pIjVrIs5xbmTk1n zO)0pgbbT3`fdA>sP9`pVfn$O3#(!e~`is|T6YDDgTJ%mSir>UDZM$bc1GZZl8`&J% zAo%iW3y$3>NBuM1c@16_&aH#w4kmTcIx@DITtn`}90-wS2V~J_LO9_U4SncLz!UxK zqyz46BZoY)(MLWr<`hF?tJ+Cc+5*XkI1|_DB;ho9=`V}KvR$)GskIX?zz~(jQfi}< zxw@wv0AJK??>7sOwa{4BX(uk?uKTUkZ28QX0aDkn0-GR&!6JeI?u z8B1`N_2k}MAro2`?8v1ZZ@xS}VFypzXj!&*`|t;E6}i3>8wgl!on#rWo}ddyTjuO! zpT5~YRiTRt{20VtFYurwcFYFtBU{^c?b@}YrjvL*CUTS;)0Bn{lNx8$}xryY#;sT zN8xCQ12a8%^PAu7`0~ktQy?*;e=!#cd=LDTzs8SK7GNHU{-^)+pZlG#b@IdnDSlU`CZ%J`}==yd-TyqUC({$A+^WJiU)S2`AIRx&@B_s9u>&Q*lY*^ z_O?I>>=x}8*89@V$e!)&|f9c{Y9>lUSwtKi z;rvbC3ol&XKL7JSfBUj8|FZ4bXP=ekU<#=PoQ}e z`fYE2`*!p8o%mqxGEW;b_OXD@KBr&>V}n&4Ph4I+J7z;KIiejMNmF*Pod~t3+e$+( zdp0M(XAs_r*YKo(*Iyk~&V6$F(74MP)Z#iNLaCgx_d(}r@s*a+RFvnO!yNODnhnPZ z#77x?1rCXQs=g%!@IDvPXBeYTKSy8L=$A7fD{-xPgRE%dFSYYfmc%L0b;;!p!dK;-3u z#GnmHjcMXK13PUk91EbY7}CnB+Jgmo7&+~Chw)DH_!qQGo4aB(-HM-J`0x&@%3)I- z+`t59hd$n!BA#_nI9Uc$SN+=A`$1X09G{^p4ma)jte+u|Dku)(L}Q2-s+&6|vIi$Z4ao+qJZR1np(^I*iG86!B{#&H7V(?;JD)t9z6z3B}(iO;-ZY{Fy4dgt3S3;KF) zd*+#Ex0m>P6yCAV9sJjQ!t1?E+&~!WtwrGo0eWcv3?zWz@*x3D!p_T5KCH?yyJI0k+8s7kT;+1@+1nsCGbUG^o843e8pF6 z*RS950*0q^yx>CLS1)2NUbvWx(??O3N34vYf#E`bIUiZ2uGPXC&w}8XR{g`f@;(kCNlo0R_&iFk3 z_+$QnByrF`zS_k1kFWZDVE#w?Ui!{W+Qdpez4+~Uibk5CK%E}91Vi2s>9`I((A?3> z01E7U?e0PDuqkD?OS_c78Cqsc+GNY?m0f61 zc*q^-ufYlYPVmajO6V!o&YS>k3L_QyS;ySVcUgF=eUhc%!vzDe8RU~31xjCq$cC(+ zHCxdK#a807Xg6j2)Gh_F*62E!Ce|f;Twt)a)3lH5qJyuhammK63k@DQAW@&qmoexE z+oQGvvhV&&`6`^}kRf!+jPy<(uu_HxO>}t1>dk<7%7K78$KIjFj&m%!upQ_Cif|f+xKVFEmbQ^FmjD9xP%b zHXnZY;arUJox9Lol#`ECtDHN3aeLwU7yZ+If4qf!MDM}q@o6sqU7T}@oG3*&PVeUB z#d?5I(w+_ange+*f`8;ket7%PPyf`$uagp=F)^<)zq%hnZodHZ6tZuW1-(dLXlbmhADFa%pl7T9(_!d9^H&nLE_-B%138k^Jp$VRPqb#>6DHpy~W(hudNhJ zm;{)uL)X_Xn-X8{zJRm^%xC1p*nOp;;*Atq+O2-`a)h-{mcFJAI;=WNcR?g!2BXB; z+F8t*4iKxJB^SU~uWbMHAN`~4&-~dxyFK*KBVK^P$7jC=5}iG)u`7S!bSgT0sy=co zU9KctJ%0=qz&(;g~zDJbU@2S&2s^*-&mQTz6 zv7Trw+2Zfh&`;&xB3o!Fp1@I8aB z?#me$#+e_3`pKX83D>-ieWDNV$tRz59rOQp35GNI=rixMV?VLax`Q(S8aTO<5CBOr zCib(`(%AnZnRv-7F?T%&SbusB;`Ew*iglceWxK+QAy30Tq8Z$;y`+#Qex3PlE_7RN z=Qxp7JZm^}`lVbn-nwyJJ2gHPaZ<%zaVrjrTdA!kl(!26e+)P`}X#R z*S}$V-`BryyBS}^q5krj8dJ^(_mg-Ff2N;vg4^lzjT;lsJ@>+P_jV|8bN9}j?Rt(~ zZ++{}(NgU&SJv3faWp>8U+li=aWHmSJ*W*GyyR>UN@XL6xj>M2`YW^NHgc@tWG*>& z^atUTw3sd2tZ+W^eczCMk|Br}Sx5!vrZF=8@gw?x;f{=j5I~rN#1Ja_Zeob7mvU~>I8)TO2dcP!gapMjXt?_JPdc_}C)VjpX_cc7oww5* zXn&^>s0gyuvo_0Lx=T2@O`Q6$8GZ^=mytE5-7vbfRZ7M!9fPXWIcLm1x7Yf%$2;?G zf_e?^gU+Y{Cnkubrd!z2Fpybo2d;X;&M3O*42BaNIs^mA|0#849{3v}W+x zd7)2Mwc$>Y*P^*~A*c;spz@41wwfEXR~`ZS#D$Oy37ASw zVy{1zQ6I>=aJyXQN4R}B1uG5TyAEe=$RcJzr}6r|M%u_A zOTlK;*TIp+!UdZWS?;=?cRp3VkB4H59D{{H+ii1KKsTT(XxNxI?FTx|HUWg9e@?P4 zU%cX2b__7^z;@@(Jx>C_4S(^2Y78^r0P}!11mkROmo0}WGLJp_sCUSho}V;CM01G| z9ly)P_mPoGPO$ah)oa^Z-tuNItjUp&10r#^KaS--6UwdV^_R98`<%92IKO@D>8H1U z@&5Pw16!mRdS-THz{wE@QsSH#5J+jh*Bk+Y5vaB+x631UAASa=f8%yl+F$i5aFIQ= z3%2v}u{t2;iX)4^mbxCh)acFpYZs1oR}FvD)n&;7C>*o1~m#TEQP3W6RtP2&}dFLkLQ={UwHO8e}mxn z|AF7XJ^I9x+w~i_{ptmMT_<_eelmuA2rMelbx@iVki)*ZVt>H7uS9)|6*vhcHf{nw z^X#+Rg~Vzfkc%LnI`U{R$6$Rgn=mERE;Y8-xb1SGt%hU4`YR>dcBXB3)}c*l9K7S7 z8=JPZ{FhfCrayXp_X&J-(4(le6FpDA<+2}OZ1mmkIoJ# z`C7bwr#iShTh{tGec}3z?F+x~3%Aex+|S;gPo8l^ZY-*?$z>$Rm*|;GUW78Tj5{OA z4JB4CZd~(yeU9b)nmBar+HVyj%{VgmniohNlN4yhhE`wYjSMBWe8rD)^5!DvAa}+G z`zCa9Kph*>u@%IdQTte+-(NoG6M1yViFu*J=tidJHffH{<)4=}APeNHeJhPT1{rw+ zp^^T0aY!?MU>i>mZ3m^@LK9u$A2~#jTQIT;S9<0kZG1r;+&-jGbu((&z@ttO^=%TA z0hY_s2O?{}H4-3)d3Aj(zDzKNkSjXz(Glp#Sq2bP_drK(&4r!Ts>t35jISeovE!G0 zP>7Iyg`5QUVjeQR$}3H0KQ&_j5833vT2?T|6g%zQZqo@F_M*QAXQ6wpsVtbNW^M{_ zN?s2DtKHi9up^5$6J=NJ;8b=gFbNQ#JqLu@>I1Z`ZbLJ^7?ItL^;)3NUwv=^RI@bi z*sh5eh{(``WoMz1K0999Ctp3e3Tb4$YbR}NtQbbt8gb=EW?})RQU*Wtfyt~Cb}=_R zK)n=N-3beohbICvb$1q1ykxD4!v(8K`^yC@3-L=i7~M@N7yj(9EGX=l$twpU9%aLy zzcvg#20QLi(hafFPVqnr)PEs(U8E+4#&v?p#*&eX4z%V$+EQTwAs+C=T7iy10x%9f zP3fmQFuQoVDCf<^J_m7d*!1-@R>O9vMTc#sW5|Ck}l!4zpss6#=+#m}~K8-M)U?-a(5xqI{GjqSNy z1kiW*?jJGz-uJ#&z72e(@VGPT5%naIo4EX)65sPPoWyZ47Zrc!d%t(Pm6I>NV|gz7 z2nP*MjK-%YEP_hLw2HaZSc?7W{vd|)v~1U5A^6f?x?Zpjt$ILpdXpsJ|hbf`mv343E~CxOY6x+*4DSB>MeUUZ&TXKYUY*;c*AdNK-C>DJ7l(4=O=yb=*s z9of9AT0P?*yUQlx#)~~ljFmTQNN|2ZRW0(7*X4_swhM{tJO0F<*#6l+|DXLKEX`tz z{dL*K!rs>a>rASZANFhd-!^MTsz7ZS7|7VG&8BPR5*B<&vp?shJybJJ&S&IUbE3i; z;hcdMT~3b1fbMiTQ1|rfCW%!=-|IasiK>VXYh=F|`w(IwATktLV$qO4EfrH(;vOgKD9a}Dd~N6I)yu}njakU_+j*`Z zY~><5#~^w`jQof6o8J6JpCoWi2p>@|ep0ZpfWr^RDe?d`w^dj}qJfk%xuvdE+vH{C zTc~JKa+-fYFJSNmt!2Nsnc|KdXufkUnLhM}660MLx*1nzVjdj?7(b2y9hH!|Yu@#Ko`rA9OoCNU8x!i3|4pMx4DYog$I=Jyku-3VIHn3!HK;DX?i`(${Xk+9X6}Bp) z1UFysG4t-?MLt1KJ2D-OTo{sH45D|wdbR=NBu&3~J7KZWHXBYJT%?0@-omdmKmOzs z_7{5`g!ul>Mg9vp6!1Iu?syW28Gx8>=c4&-Z+qMJ@I!nbj+4D)IC?8!s7CndC9dy;#@+Sf)oZckXp7i)d=Itq*v zNu`)EZWy$G?Nj@M9DXDvu1Ue@QK(wiK6#~uK67?_=|dxtQ6O^dLv7cdeM;S2Kxf`C ze`vs`G>5{jm#ub#?6T01X>LfH5~@_ctjfBPOkSHW2*=}2=Qj}U@&`oMu}|q^o7E1r z63H#&$bQUU9PuMd^bs9CeO&YCQck9?=7jve{J;G9?Z5f!e|>xGiO0PG#>LON8Rfjg zPxfs;jjV_GIOIhLjx21~0b+)Z4f==d$~1Dp$Sw4f$*3-gjKs2sjghMr?5ANxf5J7E z+Fvn3u^q&dVii^$nsm|7Xf!VLys2`4#&LqhUb)oC#6f>M56kOGb#Ht*zA1O^-QJ#h z>Z99N{JO8$e)*SvSuSS!X(fNVLNt`sFI`yDv)HZ(dF}jgE+PxxIX?6hj$b^AYO;{q z_mLAYPd@O0pA0trj~KBsR~~=tG1ofApS-$%$1lI`3mA$q5-Yh4WMAwU&|0|;uIQhPL2r45Z#=p@12pNsk6_0q?vp%YFekA^4{zPLwY~El@7jL#um08BGfzL| zoa8B@dpS0St*$qrFJ16)ZJt6}^UHBb46LZ!v@+k3xqJK8_L-mY>3&C?KJbgz{+$_0 z1UmXe$*wg$aLf7%TOagoa_M{u*eCJU9mCF@UPOYCmsH3`?wmG)(RckQlnVKj94tqPyZ7r(QoQdWdx{YV=Mf5y#}v@&aOZw+}>c5vIxVc z4h?(__L)!kFri9i89wJ%&)|0(PEJV*4{)FfDJSxRvgo9Q#DTOF4XW#6G=R7#lkv4C zn3Dr$nx{`ZP|d>20*yX>Fb(a8^39Agg~40)jA`@7!+&YQp%bTY@G#S2`D*ihbM+leFHFzO!I9{W;_deO??^Y)Z1?=TqS3=W_M_+iGI0RPj5n|$8)J)(J(+*->Q%q|1Pe|B_Uy4n-!o?jIU0h%@4*c-R-MjqibwhR^jE%qZcfQxh z)z(3cPhmJA<`eH3I_a-~$T+64v-XWOMs1^qnA^Sox&=gP*IeB1<39ev3&BIvbihx? zr_q~(W7GWhp-Nl#TMhje50TJ)mrsJ23YHP?DbkMfdA&-{F~c%e&=^?4`-fV;^~ao=+i@a z&AO-A_%U`ZWE=9%6C|{6($bC}?M%L5Fi!Fq#}J#Rj$PM+6ZCL`?2H$3?qKy_H&BC} zV|`N;k70n+2TI=9BbBf)qFn6Geke3ZjWo71q*sOZm&78_e9@OR&hi7&^CFH57ccrq z?B{&$XK!EowO^YHwcB36*pI~66TtLqa-@sB5OrjdEMsGBWG<{Y*+|n`$ow7xos9fT zUD1`@_iM)ErL2EHZEOqRJeCXK$DerIiz*1(4!DnH4Ej_IabSyN&3sX4Hj`jtU@k8C z_0lT&N(|1E#MBd3SlQw?zPvyUK=;NR$nrO90)SMkWXqUe*j~!T`g*Epk8ON$Gx)&= zAByeRF&~jrwN?tvkBpFvTA$S1$R!2^t0Iejv=4l}$75^ci0fu9Qh&{_`8C@ofAYJw zXP*67E_8Eji5@bH7-PZ@((&VGJ)goU{sDY;E<2`?<(J!k{?GmSsdFKpV>)^lvu{_N z_&Uy%#=ZI#G*`tmI}ex};WKxJ1|NSADw8Vb>I zgZE(2_6)*Irb#i(&|vULU*ybfCu3npq?!M?(nA{+i9Q6UDYH}qv=~`KU@|**Wa*f{_=h zUp<<{%tc0<=02s5^X!o*Up)Hm*od*{pdVUvy2!MsIX=u)aM zH~+b|c5ou*0*Sko-sN{OqA&_2dW z(H~@(BLId#dA~(%E7z{VB06b}EBVAnjI1AL=?OVDDZ4@#D^8dp#V2X;`&b^(uo+%# zz3z3d3zB#eBYymWl#Cm;d1RXUt{3G!NaF;#i?Q|2x4%6X=RESxg?nPlqJHV(B`=75 zWG(VU=#7PF3ZY%fg~t#7$iLh^_>&*>aqNG&q+%EqoSaf<2dUVgqGC%6KvOT~pfC7{@W3luZ0^*uDF>>Osdhu3V#7-7F zmr7f9t8bintDViBj|13347-lb2}&!a_Kv`uTin^F$PKg+UR)dI3%QlAS+9&~%?9Mj z1Gr3(lk83#y4&{2eaamwl)aDm3_dh9Wo6@=IB3uQnucF*pv^17@Gph-fuHz^?T>xi zw`G1_-mYDJD9Y!2G?qTyzH{3XRlX~apRSLMsnD@?#V~+6)wk^_t`DH6d1G#OIiUHe zna*Y6uHBTmDA5D{Lw_I_z5I}!!r|9cHV6>}Z`suaoTcm&X<}P3HX%$UbR9*e)t<@Hrr zWf%|8@oBCx5hbP^^a|7m<;CkSZXf;VQ`wJoAdRPA-u||?WnNtM0v&(aOTU;$JT2e_ zO^$o&7|<9V2g>W4Hhm*f#v%EF&MP!~U=9KL%A6XT#xnYppkAy)Vq;9vwWdGFb&k-T z>o;%o*nncd<4NSP&s;vAew2ecx~X|BTQw_=ztbuoqWz*h77&!a`qJZ=K83p zPrh#Zrf>Z1{=Y9@nc;jQ(_*`R{if#=oJ+W-YH!@A-wQ}S-L{v>3qM-+hBv-(pIgXG zG=b!C&WX@>-%Y`)V+~>=f~uQ${C2$5@I@jW%RsklU23Z~(23mKY~tyG=5XnyCYDtF zp~^K5i8o}%;nL+x;_&cJjO%#QbFRu_0|XSX)(u$4kUp&a#5h3lH?PX7G;pGo8mXE0 z`0}R4K1Y$83ZCb9)DXxqF-+fdOq)WZF|51*(Ca zMj0AM8r7MJSo0%2_NLW(>8dHk9p?c0Pt8!f7{tgv*s5i7A59FJga8vE)xP*Cv~w#v zO`}t{vJ+M1t&m*{LI6F>F1ZNOfHfhdtqy_`moh_(_OiknwDe~Uq#H$~M+QQ0U#aQe zK2Au&8(Dx%dI1{f7AMeYweYgmZf&6Lqf1=u;xg@*?%nZ+kXY0U^#QkIcCuG&HuU)* z>vqNK764R zCqc)&DjW!1-2ue|nhJfI@&CYfg_A1+2p79t7;@m`?;aN5M|&Dd!H{Sz!IMp)jQ|7+ z`(5O)@%ZD9W-eu6u9_#${IrNSN3fNezbLt#lMDNUx`GdE?|SDuJrJ}1~F1un>-WpIr z3nec)^{JoQgmkc@#MFhcuSo(ee{5tOp80R1Hfvxa&$$QM`S3@n+& ztnK1w`nDka=9K(x{yH!hKfm)^zQwOwT%R9p@|dL^6|B4=hkf!)Whu`SW9T05rtiq& z3!ZS$iwv0|i25mTgXCi$``Gq$F3kP3JoAZoZ{NDTz5b1_@7iyPKJ#1C)yEzo7HYd_ zIP?JsNpgyLfE+u}Mp~$Jh2_a4(oy$C$DYnUg9a$Mm@pUfBeFQ52y9r}&zQ=k8N zpXc9Uz3}`CJ&t5uM|Q2RD}QHV2#Q7i28sA?-MX_~&2iN41E&uiW+Xo<|jOyyUkD<~&ME z*vt5_-9P7^QN}V+yR;(+0X_ z@6Z^)*boOeFl{9&x6`7~`P7&loJHf^Dy6iF>M3|-3+M(XzMSj8>T)-B^;%2C!6Lis zD_M4+YfNfO@%1Tg_nq1R_P7G|6q9v}6W+v$kIXuVo*9vVlfZ9o^yJvbjw9LunF*7@fTsl? zV-0PJVk~G*E=Zj)^#(0vCKAG)ydXC=tK>U6nG^?EVn(FLNKO>Sb_!n@=?Oz=3I_VW zeWMRuUfyeQQg>|X3sPtU(5qG&I=)6{{=p%N;)DuD0tBEK%s8e0x5 z5AeIkny7dT8c7=7IprX$lPP&4M{W$BPZfvw`q#ZaCop$&B6Guo>-AjZy#5WJn4K?U zjk-2kd7(KwrKCad)dT3rO6LIBM!!GKI6zC`hyv665PM!hwKF(iAJSj`V#H79p|4^F z!gpn7+=HU%qdv@`kvOOUt5%*DNF<4DJps@y+L`kg!tpLW{Pf{o6wsMZZIS6GF+57g z-v{B7UPL7M;v)D~4v;Gw_Ong}<&MGaI48U9Peu4An zFKr)t>gnyqi`R{Vh=`X@e&6!uH*arv!|VOD#`(qNa}MA<4y`QX6+iHu|BhcX!eh_h z_kDkVyYa${{e&%ahSSh#2z#^#7#_hY3<|BjR*?j>Qy3irz)lHiXd}$lPa%&!1_f$2 zgk>u2-i+u;Rv8rLQXsk1g%>30ockR4qocLeH7KC|at3YLJKE~lAX}efLnqZAYo+Py zU^leVVV!LEq>Y>)w`ldQ{oQKq8uJ-Cbz7LI&jpo%yJE4X-~^sAEglqNh{o_e3HB3( z=B<7XeM@azDRyh=wF+o775OX997Er@pdHrtTiMtConP`xQ~np*N1pmfPONWdsf&!0 z^nvZlrOVru%wPT^_B{Kv_SnvN8$Z5gy!IM@6U%}qw4e3A^xC(Acz5{7Lji}M^~u~| zgJVW??ITraEC{jLbpjhy*$j#;d;YoY*MH@&+kVLx{F3d(ToAiU<4Cz~+I1&=~s^GB-8du;KzxN+seftv#zXT~M9D6!PpOZ-m6_{C{8|drmX1TOY4SvXj8%%?w$tv6Ys7LyQ?AD)3`JW*f;^f`5VV2J`@9(GM>SD!iP_c^p6Nces-YQn_{G zfLA(*A?K}qh93p@D>UgFG-by(aY{|$?fw@~T}kZ{s>h)StvNxd#kLm6w;$LFZtjN0 zTRY(xL;EK^Eghjl&S?kegZnDH^vk{kx?Yr4yOm@A6%IKt6y{@aEo-87*nf}E{)K7` zm9g?y{A-g~j3aN)C8iHMZ{|t?WoY1xS4s5)9@)f(Jy#d>$q^>ASuS^-(SwW(49-uG z)%sBleW+KoX_#UXE_kP=iTq#-tmrigtzV* z7mS&Dp{0aJW(OLtmEkSfq5z0 zIpc**+Th5tcoGYbZ>cCWPt0*NP2mE=Avd7dh^&h+cX)$C$FMZ2;2hZa?p|IGUAyKF zd_cyQ2f^_956Ak1NVggnz~Z?7$O|yIzNyU}`wo4JpA=3^cpUo4C!fd(9pAr-Ef>v* z#XsZ7IX)+WFXUp?N2!T0@!!0CdwcZp$F{e=^{vU*e1}@y^f-L}wu6%)RIXjUtgQ!f z0B6jZnpZ;OQG~VFQ6eiHMmvs zq8$u9%xRIQs^Vqm{Oj=sR_Ba$_eGX15*dQHJ$|K>F(Kg2~FaP2YHQtn2E zec)c^FyE2q$8`R;|Ka~;`^sPU6|Q02+@ptnBAA%?6?4Pbm>)zRBi-tm9`SjK8mo7cPa)_js#C-)|-FPdxs__P(!uUkIV_X)rIl zhK-qX4gmXPE?#4^7CLWl-?_Pc=4XF~zf0o9H)$j9d1GM>f$^zzD)L~al;1HsohRkJ z3)XT2E=_$$}=E41p=6G6p zEEA{=k0+W$f60!F)zIaogceQP#JKoXflrJhE0j+@D<2VX+0C%2MUVV?d~ekBN$Ton zVr4!t{}!kkVb-g9gz_5P52SDgfCNi(U>F3T6RzOIpiVhMQ#2F}oOE~E;*VXVYIT*u zng~1Kd-w13I>9b`(D!wO(NMO&4MDq^RI;;a2LkoiJ59_cg{2ji91t4xBPl=x%ZIR= zUNL}Hw|1#vEglCp_@yn`0&zvoqUIvE2r#NoRrxVNoeG=YNo3Iop^s5jh!-mSV2LM5 zw6T-d+u#0nT4*pOF#6q{oh*_Mu7`KzNgxl?sE5kEmTXy<}{Eia-w0E>eSR8 zNDpv`hBOu^L&ZZo;|li;<`%WX_&;jAy%=<_R}{vF1?!1u(TPl36^&P@%3yC}vk z3uYAY#}Al%G#9L%6OAsi)SvRnpX_7Mz2lh0bk7^Hb?$KSj4g6!UqYks7fpZbZ~tw7 zwUfU~(tr4Uq?)m+Epah>R!~-BV{_!jfAc#aJ_USlqqO(~#s)&(MzYB=8$`@)^>HxCPN?Cn}vfF|tH|^2i!8URWUof)c+k8@%{L(qV&Ki6bVeIT6 zeQ4kmWrFCdbD#inlvTNKuzNzg{`Bb;=Ik&cKu+8bFcch4^%#e)k9+>uA~Wp@)`oJN zOl8cuS%WX;C=&c4@uiEGw{QOKzkU1n|KRW69(nlT?M5zyHG)ZA2x7-ru)oeQMreoP z5sg?j4YmM2Yt+(HIvY=D6rFf6Ad?F`7>geL#LzVk>TD>Q99bEG(3nly(?5Mk9lZPf zh|w?30I<7cHQH^lvQVLzXOIReK&$MMN=Y8L;lKsT^UpuOz4fi1wEgbi{kykwx!CmY zh|oX`U2RT|c3VM{?{KCShzML#yo4s3W2fzvhjrtVfR`0+d?L&Ix{*2X>@&~#!%7%D zf8l~R4nOhDpSWGVd^NGJi_nxf#Reyx*x+J$j{!e8Z>tJ2yVl5C1+X?!#gRp&t-BWflrLWS zx!?mInTy;co_(0MklMA*cI0`5P3gV@eRO7P|J*qi6-e90*j11>^faPlBOHlHi@@4_5fm-3t{LE@LcSbbQb1f zv1>#9^_RyBl$S_z%Lzj1-EJcA7Y9=w0P+5j$WSPW}D1bWC z7@uom2<$v(WDk7gGwGLmca#WI?+dbYaCV-`NeN!da{`$@bF#oimp@1mJ1Y(|mjl=7qBpjJg9(y}Bb6~zFGf#_1@*Ce z>aQZQG}49u9v?Nk+iggpkDk6_&x^S<`=JOJC)~XV26`78G79CxLl!!H+z&#-2O3uL z6@;`?!}p+vPAu3Tu=5wRg)0209@~3PMKX}a(*Y0xkiLq&)_z%b% z`~XYrp1W|q{SI)Faw)!l>;oUz{^>vc=f>ea86GzV{PcS|R-As+Ho)8yKhlO?D6P~J zEZMT*ExCcCJ^hor+UP~j$jhs~sI4GjSD%xa(v`#Ru8&Upx5oqQria&N0h<1HqbG=s zGj<|-f)m|&u(KxaL;JKKEFxo=ZCLxGUDH2>o0D<=okOu z?T`HL|99Kl-~QI^>8GEHeC!}NbB(@p(c=%v)lr}|&Gn=JZ~4lMT=2%qT#%q|MXVVE zbTfNAp3r6ufW(s}N>_K3*qWEv6i->7pg=+F>`65|IeAHSEhwb6o7D%jiGAyEU<9G^ zlLwk`L*P?Be~`~Hk`*#1qqHCJaagkRJHPc?w%2{aC-{S7(7UhH{^ZLD#8QumH`zSD~@ zKD8uHpM){j7Ujl)_EamDkyAh5*L=b%m!2XUI=g~8%MMC%Z8D@Q zCx|FJ@_e$!+%qTHM|c$4+$<5Hwupn@rQleAd^$K>;;g;;J;BKi^x;dx=V?EI&J#_@ zx-uZDeE7^!Tt$at3pYu=^4I@*j}6zaU$_{$K%rKK<8Wl9SVw|u^*0fbI?Sjf)6p3DACt` z@w`UYc8b3Rl7Sv>kCzh%=vv>DfmQ94S!XTT;)vcD!%&k?=LGHDCPt?Yto3Uh|MhX0 zyUIm|sJ+k<%J+g*-b!q3j%wiK-)-n!-_w#l@=KRg;A8qA;6vHc$PwF~Q&IxPd%rK% zoROsszWb#Lm)McX>nefqDGcA7NuKs0HW;L-5FYyp ztSR{BSg@}_Y*V%WwP7zHs=H{_tq!Rz{WUlX=iKSsqg+NHt-J=HnesLrkrY>#a+Yit z&wvw*GO`_tltICHcN8THdmC9|2rfIrE003^m7q&^i~?d#gwU3swOFr-uqFz=oPP)X zwWv4F=0iInob+T*duYmtm?C*Yt6DFF1ScztAvTd`9AJd*7CLQAbiu-w7qP+3xA|>+ z>}300GJNi_AlKRp3*Fg?Sp44~pDc3G!-0nb5ho2R zADmQN$N|Jhtajh=%Hk9r3oXZfV+sG1H%f@K$JQy3^om6>u%Fb;I4y}nPr88SiL&PC zY-5LP^MfG#z0ZZjz++21Lc))EtWRG2_wXKI1b!Jtuv9hcCJC z(Z%#PI{fGrKj`73ggBg7c)XE(ox7M5vkT|8|NejcA3XW>QPbpx{<8H~rh_q;d|Z{2 zCj&pH4Srn9{g&*K3+L6U6>Pmy6Pb=tc~R;B*I!aW+>(;}m1e1r^0OWW2_h#36}BU)SNHSG~q0;0!1dMFbIn zrl+dv8c&^5r%qMf&-?TFe)ry|y3H?tKz*NQ?X}i-Uf(tBwfD21=b0P`E_PMt?edIE z8CGQACxMtD<5VEhyp|`oMA>c^Y)d-4$+2%->J-mbzEdcC#W(Wsb`27<5ulEa)T~!! zW-In5|9RnKeWk#>mQkWxtvvBJP2()G;Ir;B7Wr@N_?CEXXk9zIvO4a3(p}??Z}>mP z3qJPwg# zd{jS4*6l(+oKcqc84Z_WVscso57pev1TO$*pT$eH?5YISG@g*zzkk1Pj&PnkclNX& z6Moh+p5b56N2%M3Q{@xm3OWC!7I<_i_4#8?wrW}XZX6Jr-RUt-5fEEi0$2I!YTCje zut}2aISv{-oHzJIb7-)`%HJdLJ@?E{;-CyU(ReDy-}~hSo#7|i1{aiSuTDj=fj-Mf zh=5xUK2%SO#*M>_X`KtCa~nTKBp!yef@N9X2v-6{n{8L(=g(glPkzc%#^=B0^Tx`# zGrmCd7**T&!A)+qQ}RMtE(PT+A}<$3+ZPhx|BbQakK<07Xc1?ODUukmjRXtu2gc^Q=9%NI8^u5v-Y z9Wez7NiO!W3AgQo#6$6!8hDz&~aOlX}Hcn>0pZ1p~ zm!XN`y+M2k5B2yS{^&HXlBJM=ZaiN#2`7N(AcBL3M0n9_s!Ya56O`Itcs;IUpMD32 z1Y9-HEbsPCdWi>ERgrhfc*?1&bch!*)+B@Yrt>56sDsDy=!CmyWh+$`Y|e+|dE<2Pi&^oJjCjE0cXTe+fNStr(0I#;aRBw|08;DYgm=J$ z4`t?Ec4i4x2Q;EO(liELI%a}NZ-L~@YBV~O&}9UZLC*JL#6b&?H#cTuabfa7sDWxf zG7<2Lx=*m;@yW!zs(K+-g*sX3G_84DP-?xdCI(@F1{qo~hAKusl~N2m4sZKRKG_Mu z_&{WgDfzH9U*slT97MCPVdOB;4W7K(FcKM+d6l4JKJ(5p(U%0@CUu2hcDKh}@g@mM z$QaY&7p2_1Pzo`4<$YmcU+@_f5j9_f7gN2w5GqBA3;PXigd<0ex((SqE0eu!X05~*v1iYo@%Ms#6GH%njX&{t)-#@^jp8ny zI37?-t!*+5R30R_of#WI&hN&3GT?# zC%gbQ2i|BX*?+W#Gy`?V06rJ2Glem9EeSC$X|)CP1k4iP2SAj2cb#*cy$DDaHYqEGD?_|poP{zt)@uL68Z zKiF@*@+k}6p;6%*4ZiR4K&$J#ABR<(ba^$f6<42h; zUs@kKbus+$pYURhgM~TI)cVt zrnYKAXAV*@i*h54M>XfGojZ86S@z-eIW`G8=TmrzF`@t$`@47VaT%UGCD3ihPt0K- zqRpvR1?9XT$2ZuJLr?X&=;jpO6!WT7dkvV}$DTjpExzyy=W)>xnQm_?Qbl`gzY=2T zQO-@38B~T=wG6px10WsfVGjTo*zCvE3Dys0;3Eoi_4XFQH979xBZ!jAk@aTQGmFrjycuIu4{gCqt?2RuRJ~}Ht-@Zbo7?2 z>Jg77XDxpX{=2}8OHg?cYz;c{EI2g*L?_^mCnL85J8f#J2LLOxLNCaL70@e)M&6rY zcVcv8a}0OkY>x%GaZ18P3y^^Up26+O&cruOP$K5DsZcTzD9pM{tCY42ltZUxQcY%P z=E1L)YhKI3PmQ=jGdX;2Yit+^%7?T!jKItrSm3P(07s%7w7&HTE1tBj5ov=D>NEFc zx?VYl@>S)zUGhLKd`vw(AfS7W4r3ptBBp${8CWK2N00Nt({7I<}-{b-#0 zqfY;}E|TM2V=eWGl!S~jAijiwPcu0oapxJFf4Bo)@$l(|qi4s&Zw0MIFgdJzcD~Pt zw&@FY$|ma|9F`L)9#Q63FySv6V_&g8bNVbu<8uKR|FeN20aofPI+WZ`p)WVS(D+r> z8*jYPzesJrut%Tv+!iR*ap^Iw{vomlnwgq-RI2ax7h+o1z-&pr4O|^v(DnN!LmyUd{s=b zI(S`}^$F;o*5h_7QSUN&uTPc*Zy>G$;nGL644K%9Mq3oL3~cC3US_X?@J{|3%DzE3 z`=Mg1op`M{sg;{I?Vvohb&5A=@lZ8QX%^+^GW7OY+_6R-4k6v*2#5-wDNb;mT{*8s zZTt9!uYcY6wr}|sekgaG)5UQNBbqVF#TZXP7(}yg=+W3`?D{{or}+iQGILx&69LP( zGW!RSgV(=t}gL z7K38}z5RCH3En0#&Nk2Ag%+3Fr_6H@M!JwOQhFh}E+BXHvM%0t_|s{CvH9>L5BnFH zHRz1n?DrT)eNz;jp;1N;V>GY-Kj1x7be0=dTq;X`(Z);@e zTk;f9W1M{PoQ_`0)ZPPL|Lu|d$5(U7A70@zQ(drEpQ2AB{->N|+w;)%9AYm5k2$>u zq6{B>1tV?XJY%MUD2NRgE5~l~MiU3WL?8~7Ax;-sdPN3i3aQZE32z^=hX`5q!Nq>X z*G|tC%N0TC5MPjjt9b2?`GhO~IA;988$NVoq=SfjWQ&i?5c$^Z7^P&hZbQRFQxrUp zqBl5Tw$-TUt9BV=M-{k=ltQa&I(CI~^YsD;oBILfdiTBx9#%nU303*0N~%l!f`yK2 z@c2-_4o&ol934UjFpw4K8lS$ICKk?;5d4shK?4?NpV?eXLD1 z6(dTncsGG@NmfxdHitzO5ECwbGSFj}h?RWLY4}~&A#ac_bUV9c6M$D1-hd~kUjhk5 zedL$d_@S5?l1xez1~T9k|v;XeL)W&2it3JnM2 zgGbDnaPU&+QM>d_#@!4l6Sm1Gp}5%f#iPnb>p+yjA3AVw96oqZCsonGE9DL?x=1>0 ziT1z)59U*Bu-H_b_~c~I-aX@PZD^50H=7FoqO04Q$Kc$V_FX5$YD4?SC%_+l;G^U1 zfB1)Emmi(Rg49d@4!)~5>akIwFI~JOO62g7QHY-OsTK1!ueJDKPr4F5#sceDoiObS z{bHY_%i|76Jd8%(xl6I>_*WlTeKGixy@udm@uB4GcjF7DzO+9o!=t=!&NY3>7ylM? z)1n(}Zzx?upGpDZk{mhKu<$k(_U6Hd#Y7O;FV~fp_Em46mVR}4iT9DR>!kKIP}=wy zCCeXtwHeLhgsls?Xz*iyP6&YKLN5~JGg(GIQEF=5q;{%FE#ct%dbao=kLyJCpUvUukg*d^1)foN4Ds(7rT(# z9|}B0(SE|~LtSv=UuHx>lsRs0aw}3f_5<#F=#+zUz4OL3Op+#s3a)j6qCG5}tfOwP z{o<3pD`VyCInVQN`McjdZoKg(KL*VY^D(}7TsHHcl=0{vphBN93$tb08+6&2#8hzC z8R|UGxQ19VK;JmS9{#at=2Ol97asgw&kZ-+IG%dXJ!AL2ePeA+7r=C(^|;k)UfOLa zC+LaE)WT+V`il|XtUu^E_;@jAQ$m@YC?pv z1K{(X-FwC!U376CiVpc{-{?QGrNE4Lj9XcplPnb0*`l>G0!WTIN7nHcmAM_h(aLCn zZ=2`beb2jZeAZ`wmY+znUUjg?Eo&D2Mm!a#OP4N=g9i_cJMVmwze2-YS@ z+q8w~k)Jcf*Y=M#0B%m43e8V7v>f`IUr@Z$I7Ha}C_r@L)47ATC=v6vi7xtM`*!>@ zqm{KfF7$WugIOvEhm3rYoO;@r$Qh*rGtl_FXix$VE5{VX3qGIbw{@S3T`Ibv z1YE=h<68ikwji%DCuz&jK8q3{>y9qtENf!wr8oU0Sm0o=K6pJ;nRiwK#=PAg{KpSV z(tf?%riEVfy4pU(C-(=!kuILpGcOy8KIH<(xazb!B|*=PY6FI717iyRkeiv!>xaBU+GU_OaqG7F1Sb=#BE&Zuw68SefA|} zZ^)4|22e?aw5x%^9sMc8O*uTlFEl9jEgyd?Z>VCMm~5Fhu>b|W<%p;6AhD6Gjdg=@ z@YV^sZGtzab>z+>zHQ}(h}z*v>pPE@l7I@j2=L@n;x$Dkid^i4#;9J11peLvNQOc| z#zJ`d`eJG?pkk;MGx3J3oSma|HG6!KKGi{SXOjQl<9o4ef%qP)y_ODN4Ex4UV#qHc z<0>&U*zfYKlQiZo9Z+;txcGI=1WMvGUJX(e3BEV9XYbx|-+dqJjp6y#RsSf+?RVTh zp8ec=waMm_XpQe}%LOrUyc%Lpyz-y+Wup$B{!*@!5*O2)P;a>Y`k`He&|=WWVVivF z@sA8Ky8r(Br9&~|LRdI>(aEOjo_n5}@6P!X25iu;GNN&U&*@4|&){h^8$q1BGPcXs z&h5L#Z~o?g8mCU589Ru-hmAjY+J`fODXi|3Yy~n#jI6w~ zj1SB7@v1tF%n2@a#IV(U?Tu8;dz&$ojn>fsPtP~=&o(yY1yGH_4*Zk_(+RhAAZJ}w zceygr+z+attNmWOnAnlnBrp6DFt)N;FKGD%O!CSpE#++hzeL!C-^3$PY)pOxvIbEo zyN{_wRmK2qa{qQ&1^WW7Vqr(B2-*B-%eq0Iz=9n9@w*L11}n%{VE8U4 zf7`^x6uh=2Aiu1JdTK*5x$FyX)5ROec|USs65%0BOiDbjT7m9e38QGN5je#!qb?$X8Wd5xi*gJLsj z%h<^|LG%1cPkiFI?e^R1`?dXJjKnJO!V+VP(+71Rtz6V4gU{WMg-lLo%YWJd3ct}B z$(H9JoZE^nfqX-~QQe<4Zh86lLeQl#p0=rG+wfFxd4Q3yy~rVn7d>ou0Jp(YOOwe9(!&LddBzLh3@*l=%MIY%zsLmzL_fSq-Y+>-tgSbAH+T8+ zWE0N#0BfE5Wdb2MHw)KovQEX(@`cZZrs!ngtOBhr7!t3tM1QcpPJA4T1~`rl(P3V9 zx^n61Hh||Zyc)dUlG~mu)YXw0gW%*FFZ&F4#)H)g$43L*Ml${mv{n1s$v#jfnb8&7 zK|2NI*Wj_R)dSuU%Ao0m&QKFG3$&p4ns;+h#VdNtTW|3K){$aC27uWLA~VCJed(8Y zrp3vlh2dj@>RE&`$Xb^W)*Efc!el)vI)}S+m{KloLvI#~V*(Fi!;DWHD`pd16*c?ez&itJk!M*(M_B0V#hh&Vlv` z53ALx>`!PUz^_C)J|ge~Hoki)nVgLHYY86t6=%+%hzM*HMaczy!5f;Ac-W&~}X@zW4OdBae*V`@P>Cdw1^= zU;1!vn`+|aJ73Hb`&GVKVFN|WkP`D5)K(qUv#vqHip#vJkL?pdQ=S;ZORRFIezVT@ z518@rp{HYo6(@9qS=gFjlilzGZin)T7rMr1uQ?E>wvwPLpLM4^Rh66Ho1m0Iatvm{ zxPZ`Rh+Ija-=zZAF~ob8oP6xEVD__o5Wd$dgT@eGzLK#qmBY`06F-H-Z}JBea@E#( z9V91au5JSCU+o*?kzULv<--@k$4{ObH{Epec*8&ZhvPM``TViAy5jW#6W)}GpHHUv z)qHLQu_)4KsElv)A0_2Rl;28|U&6O9om+vxbx_J_E$1pw)$-s=p9$UH77D~x+S}O3 zmrQZH2(J@$BTVNQh`mXU_G&%N8hUwL(mHWUG5f+Vc+Gg_t6n+Io?jgsiX-a;H{#fv z`GRFJ_p;>c;2h5gF1E_5%Gm5RJAe;GSDPu>FUh)Xu(>XfjA`hQzuW+A)rn2#^bvfB z%(05i+E*A!yy^U$V?qc%fDa9n;3dZfj4E5c`pwWf!$*RbScIn%nE>zHN2!)xHr!js z*|X=ohNI13Qs}7SFZ0~Y!gn8pLqJ)f==!ui(>L}JH{!b!j{#5Xrf6Jfl(6+u#-R12 zT@$Fx6301;U+F$_s|FUG|qTai~D20`Q}K-{)?DOQq;8f*{$3ih@g z+k8H~$d8$=U-JL)b7NT?5++%}ROV@gge+RAq;5`uuvK^4Oq6X5wjQqwRFZtdY~qz= zZbp?3a9In@se_dW7!+6UQ{fV>)?9E=L?8h85{K!6+_;v9y>2j>9A1C8V!z0W-#F^* ze5ayP`V}1hV#nhSza)lq_d|bZGx_fn@Z;zL{|1X=p1I*Rwhs*|Iu3<%v`|E1eDFeE zZR3Xn1CFKutALK;_joFdLB(lb?qel4#vZ8#G=*rlPC(kE)8IB3<7Qj=HFyj#vMZJZ zPs#D419kMk6~!H?P*3&7rJev6IL^qUfVvPWyJM(Nyk-;xkwFI(zU8}~8DV@+C|-7h z5_l$?2P_y(0?WhSlhWemMJ?iP;M`Wi^0N zu9Euzc?P_3^3(2@&NM1AhPjk7vPz}Tuq>NYb=2uq^Iw23W~ess=+aJqpA?;iimJ&* zm4U9KWg^eGCD88B(_Y(~h zaKL}NVcnW4Tnraxq-IppBB-9>3V6 z9y@+~oH}(%<1K9JPOWd${RVE!t+V9YnJsx{8`M`UqBu%neWu#`?%p4DBx#|C?VsrkX|#RZNh;GE^%?U3hWOKu%>`_UnvRidiiJ^08)^4q{C=%d=rVNX1%DY9MA|xQEgiP4F>PGeXMF+j)?UyT9ZPx|QZJx#4#j7k z%K43mdD}<3%6$qVe*Vy=*eQR4ZoGZ({I^UIRtGN0Q{+TaU(^cp9Biw`MdEv|#z46oM* zP-M0COi=b3D0Lh&|Eg??l3CL}gPBxj+!QKIW}Lyq@~^9|#%(2ms+SrAe}u(|-_*>;K0fiE+5jxe*Whu%L)?()3MkO|1h0UBnEgpa3uT z=(TH65D6Vs_oB2A@GvZ0;YBbTe#;5xwsCiqyGp?d7CIJjh*a^E9o#5wuB0EJfz3vz zWlSRPvXW7%gs<%`^OUU@9;Mtlqi&J`J)DF+sfaU39r#YIKQU>roh-(b^9eR58`V+b z8f1>)HAgMJOnOS$WzZwpNM>XEHvp!r&f8%n@k?Ls6Q&Q$fKB?Q`iD)>_8qza6WxE! zp%=eWnNOPKGZ%4yHgE>et*?Nx>&x~uT|N*qwi=Cs2CMIqSDi=i&YxfPMt~ojBKKHC z?Pc*Z?qa;`U@38nvdSQlL|{%_))j$cr=U1|!m}B@;f5Q=;lqc$S%*$vFb;F^nz)=j zdv+WF>?o_xy=0of)bT?o5 z#h9(?jB6fcM2qTdGcdKQ@boueOACDT3#6e7ij2@2^E^6A)d!oQ zPC{4fpJN>h07Aj}`+BScrt=C-gWI3hoIZPQeDW(^KHm7o|6|;I4#G`w7c63lP|xM%(`~Fd-cN{@7!g+s z2#UaubC#~UA@ZGz1R~+*_&@@*(RUr&+E0&1;)V59nw>w40WAZoIk~cSF0qXF@ zuK#+Gi(K{+w#Tn0=cY72Qg-zEBV$z;#WcD#aL(MbXZN`K?z;#7GfWh`AIcZg^L z+tyX2`8u5%90hQ2)mk1x+MPy;>X>Cd2Ok+L3rFfi-KdFs!ERWpq`W1!HDO{H{Q4aSRqcjEUyz zb}%Rpp+&wiN+0Fyv$zj^#> z<<+iuLL7_~Oa&F=KQ6dRqP+rebIgdB(J@74e=Cl*?JNunUUgvcQ^p^nD4gq{YVpCLh$&c!T$gfkjt+Xe7)?+h7KzQi(BRuxY zn_x)D0`M1)X{x(F+a^GaB4@hV!Kd%OSQSg+ObdycWYG<-Y+%9dH(q+A3paV39Ue9o z2M-(?H{JLIKW0V@Img0-tYhz3jB(<`iHgb0zjXFk@r67$TY#ol-g>KUmmB8_r1ZDhj1d$K zy-WE9Qy2KC)lqf$o82qKG+&^rSTwpJb3wK>m$KQ3AD&X=s!zS5I$anZ7*uzrx)S4f zeM9RRkIGiRvW79X>3inGhHRWVb9OxI+4uSfv!3ycj~S;=o$>`B6UVl&gI;2c&vrQL zaqNO)ZqlBVgM+F z+G&#dVukCFZ~NxIJ8r-2cK^;n|D77^QQrW;2jBQ&uB+k@NW003^Oi07M330JrD6@l zCIYmNo^LP(d#Q_x@w@IGyB_}Iqy_vtz0t5mhbYxwoID+Dpv93l8M>oRp0m`3VJVKf7CY3DwPwD-FtTV zeC+WKM&p9tpSb0gTgU(MKYxk;>d7vUr1;{+3*)xiZ}+FE{+f?)NOBS1H&fhAI6)an z;rR!t;NVAF`_CbRY#Ikr;5~+E1*+q@V{dWjq>6`f{NbX0)Tg<=s4+_mCF83}L@T_K zcbrMG%^0Q|!mS(uN_gG2gsPZ2ccNXniI*TighQ5S4>nv?E5)1d;-}?XXczviS(sV~cP)*Nh8v4a#OudOdjw$`D^OgN;aoQF~uEBo?bWZA^ zZwh@ug4pz4tOzb;7S>D@(JSvxPw*oPZW;{gRR-OrPZ9xjo;Uqs3xDBj0%bxJvO5}l zp{QFUliIB4iw)R);qIECXga3c%Bl@!;h-Xmh93_#RtV@#q-=gtp=cL$`He2fp5H*R zfusm;;sT`o{sciat5)udYmyKXs{!4?n-iVO1lBY_c{yPe2Y8HAn)u)ZSM+2$1h=uV zG2Z|F_m6k}@gI*r`IA2x_uv1KuyPPA-HRU-svmfhcOy(ov0;h?JZ7zh*SbKYY8|R~ zk3#c8)wE)q7D+8SQ}363Hn@e9wuW7gYua6xXhrs13KsQU#Vml(Hw zAobWpLF!4l6CFHJpXG}mJymyS*e`JIRfGABD?aIPpBZ2D0*c=J3)-K@185<)zcZ`l zmeAEDUA|g}*YuX9k9hT3QDesC#5=rZ4vm)z!7pjxDfq2&$qU)7o#fo!j1Q96F$;IQ zD3j~Jnu#2V@#`vO(WaQ2(Z`OB#gzMWpv0`RKI*(E8yGWu>Xb514@E~(x<+&D zV`M{RKG9*0T;8}mPM7~5O?fdbAg#afK z9_6(F)0em^wcd(BZVH;B>Z~R9Dd_EUu*z;6G^H+^ma)=2#DX8RF+Z7k)h3Vc$eW;q zozTHo9~Dd+>q#iK>|>PJhUHcDoS<9^i558bx8B5!a~HBxd>NAfvcmZSnDq`3$q^s> zg)htr^McDw(AI;1Sqh)=OFd%%Ts{pJ9wo>Xp0Qv&JbsBq%BCBwDznye0f>IYSJu|X z%U}NT@%-mLXRMw-H~5h(#yB^qpYe>R`+Lp&GPEy*=~rx_xa>HNDF$2sCqC+vk5#cS z$jG^|K$IFlo1GTGWERbJ^QtZ!=k@%ze*H#9>BDNTzv%G!4h8M=NGxb0U4{&~zqc&9 z`wG@FRR@8whRBFl{($YZ(43x&Dk)Yhrz{tEGW#Ha+1!>8Z*;ql3ZhRh6_Ua|%~@*X zC5w9aX_v>T5Uh@t!LE4m(~NMc?zId#1;BdE4OAXA9=q`7;uxDDWgdptb##Cupas@R z--_ngiZOPOD48C&hFP}D;a4hKlqWsHWn9eqOlj6|)lpoQt3C$GcJ~jXh3+$d`&;Yg zbRjJy+B}y)fi*5RX64u5Y9QJQ<{Y7E0M$a^V|60X7bY1fMmX4xJjr+w3eU?I+Gd{l zTmKRd^o9e-gk}hA=9}yZXS|Z{NDAjpH;oKl21RsR1-w+uTL2wo@d0gb=__FDBv{aL zZL93G&Iwn79BCPEPkLe6@9=iKsDswQTy=zngHr(hwgaEdTP{*oG(n`fII>-s)knGL zN+RkJK`#r=w(&k)0DnXmzWkjJcmF@|fxpamNc{+_uios(6)0`a%&*oeJA zx7lMrWnMw}J=LMH;8;tor__ThTWwM_F3R@o*^_Z50(WF{BS>t*aiUF`7)gMNe4~(s zEwm5dKOiGLX;b*u*Dw128E??V zG4ZA9~Y8J9q6Gr_Y=jzwnE{=)Xw9ZXQV#Q4F-F+XpUd zj`C_BbbtRvFWydu*lnO`J$FOlNSkzAta$;LNtDfC>?T;^#Ou&C4pGH8@rsR7R=ic7 zpz9gCB#-mb*=wfjlWg&pjX-iA)uyiXW*{3?qYPPZmbOS42a`Q;j{hv^qwAE#MAedG;wctB7OrcPLHA68ElH(>VZbGJw8y_9uRQ*#PwG*9F7$Tn*ganV`fnWH_>JG-P_3L>Df{(KBF5K9i<1JP?^(9EyRsH#bsyWnGEVzcZ7#z_JpGpI;X zfggQ2cH;Q>+|PTpe>iMq?SeLI*yQHb4*SyWN(?1ebD5eqvRW7Udd(8>Cx-mCJ#1S= zvyxkNkk&6-v}VRBGmpln>f9LIr3)zjm({;>Azw90N)~4PO*|M^z23Ky@VPia+X#Ql zls|@y!|B}N{wW*8#_^f`Pq?b@l=HSte|9a9vLuA{~6>1Tw(B#M-NU zp;J~`j0aP@3QyP#p4Xn+h{%TGkH6?FODczs?+#5Iq%f(XhMe1X4gN;h>L5Et85UDN z8K(+^huP|m39mOEj&$zaCH5-0phZ~xbeR8Q$MW!6;WRy=tTW-&X^IN0Wld%DSw|6;AbIO@+pJ|O+aCPLQ?5r{qC=J( zld#(9E*n?~@J0INI}({}?H|k}MFX7eP|r!uemGf!bxmdE@K{=XMI6m5dAAvy)gdDc zn?w5yk8CNqkGX&nm`5j})eAbwYN2OAlzqey>3sCBk^^r6dE?q>I-;Q&~j|{zm z#fej;w(NezCH$TSrzsN`fGJMud33yzJ66lA^DDkfi|yS!4z2d_U0~}csXesGk3(CZ z`2E-zvC{=9^CT@$0^$q$Nc>d;Ht;B;H~oMQj6?dq${NP{dM2=1@2DszO_pr8Y-9GMn?tQ*c#wU{7j~Y1v3dr|v;s=jh;W=X~ ze@wn*>^pd1{L#DKHU8vXe=_#&-eY?`-}^CGnt%C{qAp!dYH*$)L$7kirx296)6Ms} z9V>!i$h`90uz!?skkmW?<#N2*V;s7S4sSTBTb))b+}}4jmS@_@iVIYLpPtRlOu*X+;Vu*805cYxo_5%v4z^j~g zGoHLTVGL=!_-P2si&bUD7N#0Uj=GLZ1Dio^qT%j^ixs{e%3>uVn$BJl^3W_1^<&i|kw*t(OsN<4-BGZ9S?L*W-Mbq0~<@n2uwxGphT=Y7R z#MrTOyKi3n*SEfH{L(M~-&*57ICk&YB|XiD3^_j2M|1ljPP&a`{6xyqaZP|MCH!Gs zDy&7V*)})?CqC?m=CvN(lszV;L47>U6>`12R^WvCr2CCNKX-mbYxlXV6*hs4-aMrv zW&8H+@&C2w9Eu?wdCb9M5YMC!7tn8iEG)c`Dra1$4YUp4T-?In4_eT8WW$>^D(6fW zM1!vL@pf(|h2M{+#vSF=7ZO=jU)}rcd&g&d`lpSPCyx7<+4t|=Gj6~2HjO=g*Mhmt zcqbv08}U;=DMoh5LEv4wX&-3&m6H9110QL(LE5!10(|pG=+G82O7vCyhXF#(A?%38 z--Y36h{^MaG5x2Ex#>QEP70WWjTp9VrlG{lAD4B&6wI_4e^L}ZGdM$q@m%fG%WEdG zWi$JGR4KPFsX3NC24$Fbah~xqhMfH()^KB@WwEEdj7nED#xhpWUQdL%?X4evXlPHe z9hXEd7H|zdFUVGC^m8H%%hZ1fis<6dxbr8*Ft~r1Gb$2Cd;ly4Z{*Xql)*7?QdimW zB7v(SU|rDp0D~ZxZHA4E1YgI^GASA+b``qZw3ai@DT^v)MN&rrgWrph78C{D ze3IeLTOP9!hWN;=eHMn;&}V=jK?3i1!L(HuDm$zL@PaJ*#s(LP=$3u=k1a`rg-nZ+ z0?R^3vQ6``~;X553 zuRf5=hd3^A$tmT|E4u88?Kv(2^isTByU1*qVukyu}Jn&tnJRDo$jJd8vaCE0S!?2nShGCrpU8|BC| z7TmucmxWJ9z*>MJ>35NG{GZl>ZjZorY@bSvJ>mR#wtX%r{?KQ6z~xSWcqX|5%Pr{k zM@2R>Zae)FYU+MPcV0D)wLuL;-?D!?g;{N(XtvS}Jtafqk!Mb0cggEzLpbIs8}C9( zNBQq$v;c2|pTCn9e&@EVHqiu1(rdiXo@ODdvcvlmBjiPxu+yupiSLS<^_B(FFs2wMv>6ua%H2klc_f=(`lk)uj|OmRHs`H# zx`jdD0_aX3+`NEC8#95eRhIkeK-Ioxt4XzHL zvbGf7endgqL&Qb1p=Nz#))s>xJyD(n!1z#|3zUij%z(+sozYx6X<{NXS^NClr0Cp$^$OO-58 zu~W$)w>=hw^Jtb4_EEk`!P6zgm9`g-^Q!g58Pn0~Hducw<|cIYS@SZ-jhlHX({BJr z>`yd&p{fHn!Gs9SNv?Z-)=NB=BDcHri1@8QnFgG7gB6VuGZOcYN~IixeRE+(KSs~&Z?Q}O-8`gOEVh_*sjAGXrUECJpcZyYuiM`e(5yv? z)q|=Is)kEP76{?&m+YI|{@N!Mfx_F|B29h^a^fnSA-Ypia5Mr`o+Cv1ke3BW~KX)!qFy%+;HU|)Md)dBZAPRbda! z=!up^G@rDCwVJ29Ie?O02e{|gQ)TfT~egu>;PTR2U77DD)4q2LV&jm1f`@3DI&zv4V z^D{pqa_mLUqSnWYA<-wnL^^DN@HplqK*WxceVY2L*AJyuV0+=4bWFMhjR(N1Y|+Ab zoVp|w{oukvzrEWGzFF72g68Zo?+e(1*>q@~TYvGV9KJM-cBO@8lo3aP6t`0aZPXgg0dCep-o_v`pXFfW0*X?cthh_(5;iP&PBH`yoF;P zGj82qTD)x10&vgq2F*0#M`~b_wDB3sE?Re)nQ@gowuGY(S=rB=J3nr|<+kyC-}imv z6|Z>tIC1P@|3Fay30W5}@xu$&AO1I+zhTZ85MSJ{#8FJF0I2hIOx4|$IkKlzxRjZ zgMa}XnMcZolE;n3xNRHC19Lt5AN8<%_`jDC0+_h(L@@zXt-zZO^0!EnWo`};!0 zsNmxkwjFUJdc5#zKIqh~b5RdbwdzAs+7O=fVI&%S!Pe`Ob;OoS&=$aNRvbKdXnf=A zztQK4JMOq+9N2dtb6&CF<_2G-L4Ev-y!~*g{m6RC)QL@jdCOi1Gt7-J5S{poSRt1n zBC+L32)9`*BtC55uNf0l`1GzhVkliUC3(0=i5d7Q$^v>w?ebU*q(saa|EQZZ&$@*3 zs$-H4%w?~c8M8q9N1S^9V5h8QHkK<-Y-m1!3lzUgbwG5{@7C$%cJ_mQ zNE=`(ACW5zcDjv@jS{us@F99bFPv5RwutMFW7`O;@``PoD~LR-OLQ!zgx<&m*S6y< zkWbOgQKXK`tWqU(RJH_oXO*qM*pvmCPw=S?Jh`B%M~%@l-(0!|S3@leM8A4KgU7+s z+jlA4K@2Vvl`CaL3Fcm#?w~9InX99ZqGq*T1`-nwFCcUhh;t0}@Ay$o@G9`-Z(G0vP7Adl{>C5pda)xUPT;Lb z6%pB#@dF`jc+gCDxE#fP9GXoXHY|qRG~i`7NaI8a6sr5ded+>!brP~=1#oiF$AvZ* z!+Ug+XJb5npD+NQFPc;U@6WZ>hfa-jOZtUiD{%rg`(x^9& zm?NY)D~2nfXvax%3#y zzu>|*(E#i%>jL{wxY-BvZkB7H*qcU!@@%p*4k=ro64=b2^lvfI+F2)jEg#m%!>@tp z`OSdD+~i+)>_gasD?7;0Y33>WP&`&<6#@jaw#co=g>r3^ZHrA{Ye|K-89Su}Qg1w% zGzjNUZ{-_LbueamB$JDo?feKEK1V2RP&pUMsYBSgYlq`K`$Y}|C}QJc;wQcyXCxwI zS%E*DQR4AUK2`kIZ~eCMrLTSMICc8baqjHdd~ySLn#6DBAHS}T1;zrtIpA2tzlANk zXP47{`i#(!+!W_J5NI>Qr}3q_)d-+7|CXCFPg~{av5f6#EQ*(nZQEizBxZ1pv9@|% z7x|Bj*M8}1$4fr(rT!$`<4E@0Qk8k}^#<0DNRa}lGQV)du*a@3Rqj4&z=sr~n-}ye z6*4aVn%@_*!d=ih&UZ_9?%biVacMmG&_jL<*RfFAyLaC>e(d--@#qQ5AdbJDe<-pK zvCHyrmnT@vUkP@kIl2T*zGe+kA|~LBkIn!*j4v!fhXr0b2aN29y>E07U&MDZ=83J4 zw0%{5uyXdibj-T*bP5;98=52A>sO(*PK(xj?Gw7WIP*C}b^L*aIAPDeR9ncpUG`n{ z;8I}jl}Nxu3fOTAO!QbWm|H12qmV3KuB@CN&wAFg$3Ok2|8#u87kr^FH2tpx%y(S` z@9@)UbWrOF(6m7Crev@ORGfTV$mLv3315_mhw9#Q879Ss*1@>hzHNtX_!HSmGe7O; zg-nDp>qN`QGUTj{2t3gAH$S_o@GrCg=+O$;V4o)_=%nsOy zu971^mnoS+V0m!Lx}yWasYfOqwgWFdFrk|lyg*fOHU+4_*vMw506KQTZL$^UJJOlb z(bsl7w_S|A2~XLDY@%$#PK3@e8yHxKO>_r3j*V-3YPV2Wa$9wxo~5b{@L;QI{PmCh zlP&9@@mzSI+uwx=c%sq5vYAb*^e7{F0jf_xy(ocios=bqsN2FLAeY4jo|i7pIQd$$ zaOj0XnawAEm*Gvk6gb8@sghZzIK8b>*()m8F1BpDdCh6!8tav)$Q~!cEV44 zYfZT*5Wg?bQNSjEyW)Fhm2PXs1>a%!4>?^}bBO)e6|1ioQENoP<8F>KHu(fI?I^86 z*P~SSmxaB`liaV5lNV(_zJs?qDM*1NEXRh3{|i2F;6U02-V+JE=;T6T+cCj_(s$Ca{&Nc`aUX~r86{ny7I z{J|gke;_@Ywr(417uWrNqb-B3{3o8x*p45!H{AvdF%LgwWZEu(JpR)5>d*4o7ha~3 zC6BI_kI#k>C@5uf2}G=G1ru+I=w5R48WJB|G*EQ^pp+b(7$#}q(`~bm=d1AfuBbhp z%J3SH5#CZdFvch_@6iuTn-m|B4ZacRGKRUK0v3#eZrL!pO@86^9Pf_rq|kLV#;=g2 zRT~?MX|w#33jR;@;zf-|-}pus{NiA&YsfmsDQs7JfV8j5Qj}Pwu9C`(cP!DG5MZBm zz@yQLka4o@rqU1mpYVo%(C(|h>Z`}Me#^HAe`TCGeM$>Sei)9}(3)k8oFZ1pg_%aXtb9)i6Aa`tM0YL^w5yUUB;HNs%N}OmDX!o#G`&lNa%yuAja2Ue>D9HQOP_MDY$Ja_w@rZoIeCc$%%a0 z1Wo$k^`MPzzWFfSyfCjKsYI{DUd76(cEm>aXL8Be>EnWp66kf%>#ODHpu!v~JNPtnwH zicq2^?aDX}qzTk{Mc%Q8ASUEEbLR%g?7L%3pCK<^aHbd!Z@_q0N+%`z5ak&gVe$O6 z!$godz@#K*iZOFac!QW-qAp?I@E~EsFVH9z&M7kB7`JI#=|U4e(Dy)(A@Ifpj}Gf; zsJg8YB<4=Fr{mvyT1@pAvO3{{7Y?+*^S$JkfM4FT7#|t?U;RYAWsGix1>qGecGJ@Vcy5`$!JOF)*mM;9cgi)b-$i_926@+FJ3dgLsO+ zVqibZq$dx-G>iOUVQC^I2S`b}>@(=H=?ZO7&RtYE-R>gUj^2(ldSs@sKC&3{sioTx zq|5x+6cMK2FSqHpa9bHzYP>rg%XDuxA_xw-;l=;@6}*5WZ-l5UN{O zt`xsAF6!XhvuCd#)iYZ3iAO|y;Fn%I&dWQ)9<#i>VB-(k$hp{rxB3#Wukpcs1Yv43 z?(nJW*6~}v^_%10{q#?dx4h*o<0pRN-|AxUH?(144$_~JcSq3Ih)15>Cwy$sR2}+4 zAAhlj&usMJHNWcg)6t_x{9lVa*6ed%>$DCvW7`&uk4yeuu#EVVhW>tVQpO#=ed0?# z!8HFplHQIDGAIU7;P@g3&i24*GcP{2G4#c5^~ulu{LhaMf8@h?;y`@h{VT5U`$#)f zvW~>p^*T`}E)+SY-NY#Ej|Mu*c;t&8-ayAHx}ZDRZa8M3jW!#8DhgnqP}`pMRJk(q z#s|TI7lx zpFO_sO>Y`cy#2Ou{P-ijvDR&N94wQzEysun)>&ym!>0YIF>PQCppMQoGH>%N;)5*x z4u@4zN<4t%(tjk}(7$N0Lh`?|s3o~>WxJG7-+w*6husFieZ zIw&QF&t8Kn!w#Fv4M8@|{6h71t#$D$HpG~`$3oGjIjNL5QVg%pQ3B9uS0{~KA&Iy# zqWL0j6Hg_tXJo`pD4J(T45J%6dAjG=@#Ai*kkM<_JSNR2#zzic7dyzIk7O2l$=tDF zz4EZy;M1IJ#6=ytZSAKk;8ScHtOHXVkgu0pZx&vPwdFXJ0>+T$i1nbu@ya=suPE_& zv~TPSa`8C>G4VWi8@PN2N&i6O0HXYGxdDO1do#qZr7V#71PWw?JkNNE*B6w=i4Re$ zi7vBS90GY_1ak5jfYp3iC(1NjmdhSA9vD|SkdgFC=ss4zF*4SHshraAHiwQ zU_5p4xi8J8zJP^d`IWU+$w&^tXXT)Ttnezvmi7-+C;srpG_t*Bg%=JdGk_B)bI~%? zgI~6nal`(i$B5+(s*C3KLUOg@hX??e+{mJ%oqa!V}PUvq$2@!k{6hC z)(iwT^$D%qj}&!%sl#{Zs4Hc4Fg}^+%KBhCh3n0O2Ss=CqOlUXTGJ$dcoKi3(~=fUq1XF<1=ckkqzI8$2F1Us&jK@0P{qFxZ zR#(qkwm*&RIB?|elCHb%x^dHuH@g32#qzX2K16Sna&p#4FJJ7N@Oyat+mEwxV`7gs zI&0&ne)^}!xpQa64z+&=n^q)ENTw+{O&7Skxe-lD;z${`C0HD%EdXk0RM+P+f!5HEI` zLHRuHVWS=jz|dl2&qWw>m5ZA81YX7%Un$^wt2@Qx$8xbzI{b-*TSUS%9%=+~%n z`dO8#&cFaCqv39RlKoupn^e9LgSibHf^TDNDbuFl`}<=JOmW`;(>g(n-5$~N|KC?U zH(58o>6^ZJ+;Zz}V|8uKa?_X*TW`SWmkqwNS_Wdb@;E)&2IqE8Pz3z9jGVDx;mnJj zd7P49aiV4d{jznOIeTurq1X9>a~l`= zw4F7%?azKhU+cGQR4?!#3Z#EgGnChswd>T1iFVB?xB!*N8Q=CBrz#j**E!iUy!F6l zKciy_jN3r)@LLau0^>H-Ic(;c0p867^T)GF!6{nmALfiMmY7VTxR2O#@U=01Z^Y_a zXX{cuzD6(O7Q1aLZLj`?Lz!=08&Ab={qGYXQ&zdbCX#T4K6j)2ClC^M-xhWLkGY&i5Ux8V#@Yq+q?U}R4$l!0o zq@&v8r{%mJENFtMN!MT#aAT%`peBe7Q>UDre)nn;=WQChnxu&5_1H_w&=%0KBS2}t?0O1u-$2St1m@U(cne`-3+3HH?V?cOs zIt4i@_s&Avk%86(0Simw0w7yO0~PsDC11$!x>^SdTS~CczKJisESRxZk1@Gy+8h@E zKha>?;t{R>gts4$ji?UTkqp1Gnv=i!r*NA#my%hcB*F zwFU6#<6YtDMckPZ7hK#qN5?WuiE;k(liYfVk-+9qXaVZxu5$Ejx=Rdi@$hm8O;k;Z zlOuPwwPNY5xT?L|xHy;Gi4%|dBG`RcCes%-VtEx(uYLdpenXp9zOzdidptUg@7zge zlglzK$UEo!SPrt4~MG#{#1C&*tdVLe+BgCe(vWaci9)gD452AHCJvs zkA(Gy!&IaA)K2fd`3DV@v*A5-RqxCR31n>S}z3Kby3JF+m#xWLFrIr z^BJznXCsF61Gwm%bp>bt&D1#njXp`-*ns&FeICb^(-j4exqTX!yS8s1XSqN)r*!_@ z*t>i8*tK()+c*2URdaB|k5*4@Y#M{U*(gjh@KpxC;^|z$XA_*h()^I$XS9y+E9&3- zy>A*{{Ka219zAhPKAjqCYZv?#gDt+%CEsffCkWUfu@SCuW0*@o+5lZSF>%8jxwt2s zIaKjU-aeY3gWATF7sMn!q@FdNPug`MtN5apPl35`{OYg#it(`@`?2G!zXvQC&0GF9 zjUSgH{#--i4}G(txMrGZv`B};A{u7MZPvM+GPZ#jPJV%~&jKSm39Og#kulOX%%RGz zT|390zvn&U)X6jc5i+lTN_>C&WA1s{xb>D>{R30}t32k9?W8{)&#S94)9_;2Ul%%35Xy3=dAyinm8Ao%`KbsKzO(ab{s%S(R5RSPm|RThYlWe+e|M$ z^wGS;3Vljqr+1*?7o*3nT32#}kw<234@B~kcNLoCnaGkc(1|Lpg1ac)iHp7 za3`hU37iLmzARJT=Bbdz_rqbB|CCs==?p%*rtqemy0 zT|0MrlN1?n$$7Lk@xJ%H&+))7vsHV5 zONzzD`uh0T`|cYz-0+0l2oWAnYE)*7n_qG%1n67oy?9}LY$)*w)XwcY+}`~M_WQ3( ze)*Sw**|(RJ!Mg%4cKw?X`|$PVKzai>8AzIhy|n;-U&LE^zWj*;JaTNdfY7A2F`d3 zMy7T6VxHW!*3>*nmKPQt>Jy#*QPntnDLSK2lr&994-rnTq7f0JJ(f(a^;LK)px~-N z73?4<9$#4YIKwC9X&0=r>P;22;2EFEVJKeD&+^sS0`Z#7w&OtNzxZ8MpNqk5!zWPq zAbo5YsB?pAx5hNh@n1Hnz@AzdwHbU;fMS z@PiMG{rmP|EIRocneB?XKQWNuO-`o&afc%$&QFQz80XKP_XZy!|5vHDDO_kVU;LB; zZ4h;Z-xt`ibA0{lUN^q=+rDM&+_l~F`@%Y(q~^zcXba4I>XrDRm~|#T0FIAinwYq3 z&m>EGM5m8X1u!SzGZ*UJ0BYzZ4~|buSXa0Zq`UB&Ho$I#8o7Gz-1ywjdG+|*&-?tb zsn0}0XVhq?1 zB?of>@J=Y{fX{XE>IcgTP)=sgmB=J-o2JkYs$XH-3(!C83&z;ENPi0}{;Z2z{3DM3 zYLE0=qwPpW89)AZ@X#TDGEcu|1CG4jQpma++bXMx*zhM|j0LoyL}lpa6PA%Noil`| zPYsg4tiB8=hsSo(U#Ku1fEI7{7NO$_uU^#LK2Far%d(K@$20oO{)%QFC^+UWxES5o zBY|(AT*BCjV*=U}pCVsiy}<`)TidDjECh&%zf&!TVOv{U^HURCXtA$aSvjk`8U{Dx zQjG9orpJZ-axuE+$E9IZ)Rj42^1*DbL#Kw1uo+=YiqYkDeS*Y$2F2a+CaJ77kN!(H zb-b7lqSGekuW34X9b=5h4zU4`qt=BOdPFN;7scnew_ftv=h&9(k++VDhl@@*#;5WN zS>}vthQ5Xncs!!Z*AQt#kMmh;is|3d;*40)uHu0gy+yOH)XNq)NVFqSfd^W=rk|MW z=0aA$_<@C`$h1<$Tu;v4>$2uFJgQg@DS#vW#d={)#x%9}<=0>{FlrSrB2B=RSI|>{ zmVsg*h!Y)PkTi&9-l_tsAkU&T=}-n>qU*K(6+I%-{nWA@1PCK{M9f|B9D zDU3-ClUpVlm&&KIAoNHgAM;Bra0pYpq>;nxczGGcrk) z;s4s|YJ3%-&Fv?NC)#HKKLa!+p*G5vay8_d!&=6PmXmysj+Lb9XTYcjN+a)51ZIHa;i&DjQ3GL^UTn8Gr z8GNF#G1qc*20r>A&w7Eh3j*!R(*pt6!YhDYWsWl%xdI`nyXa~tkHP8fw(HflfNVq( zd6NH|TLomSL&;+h9Uj7Ey9K7c6$uJOlH|O6OlzqsUXLhg6(Vk8#6;wUXB`1yimAa- z6Aygg;Wd=qu0q6`Wx+|5bsryl6U>YEmUcDYec0^QV-XMY> z^M#}~!t3kftk%d^zxs2>_kQ>Hj@xd%Wn5TY@gv5pCEW(cM5&=KWK-6`%Cn)P%2~h$ zAexQ-g{|-)&7Yz@qR$=BE~l7s^it=4jQLTiv!_pKem{5o?Z5ry{?wFDu-zE~#uC3g zyo(>4l3=EwywaTZg$qLsoJ~o$@@kF%0lkH!jeJr?4!K!em;c$c$5;I8ez8tU_^uby zkSOybjvx8R{o}9x>aYBXur-UwI(6OQL*vO$x!b=W?KZQX7TtOI)zEza$(i!@)FcP7 z0bfAPxMkTvAcIfnZsQ!BP9ox4O4h+mOK7~u!5s#p0p|0$dY;w(c@+YWW`zMNmRm1 zA^zYa--aYNYhL7Bk6afWCl)`m z;9t>OR!$KE*2&ydD!jmLLx(FN_`+TU;_O)0x!p9|N=pCWW7oq2EX&tmhKzbghfZOb zP%=^}cbPT~7&^@5sR#5Xsl%1ecox)L{CW@sD~KIKO>l$nbctrVxUC01rPf*Xsngxr zv*w1$2SEl!0Bk(biMlr_=rm9G>}$)rEJ~du!AD-#EQWgI)r3cz&p6 zfe4}77hOgL4=Z>QsGz|!(~16q9pOPVAy9veeB`Kz#-t50^%!C?0A}vGa^6OjF})coMpgerzX;CblB;6m zldBt_@C0uz-5#HW_(j<>TFANeA)hA!yxQAq*k$cr^V1njaoX{n__E z*8tCzQJFbWZdwn%?@o`fB7wM8E=34JABcO9>)j)Wz+-cC&Rz8S^5oS zBt8UB>|vSt%w$|cZ$4~NV0oo9D`P1>luqMdMsf3-WP6Eo5QU!f0hV>W5Cv43Z_ZWk zIA%>kSNoN^EIDrg52o?BP;Q{43NxVB7bI0Tpj)ijh>(m7zVzb>RfF=hKb#yPIR?DC z4HhV&$*JOVy%mDv2I;)+q#k|w{`mIsWB=;M#?Suj&yAx;j*c5|x=CYbxBnJr&%S-G zpFVSTyy;EfKi>V{{+rgZy;jdJ=JVu4>z$xt6HNT*^^|eM|CaW5Nb$l^u*>kozbOWK z^A&|ND=XvK&w0-H;UE0LanC(Z9mgJi(7)`v!BZ3-n`nYPN9)mX35i+L3xqSCxK*9` z;0qdxjAi-Z&9`60(qo)B);h{3yIklJ+wVV zcDm~AHBjJ(^-vO|l`{}C7?aQ+8|0CWu9QVle!2d7FL;Y9j@x8=yDrXu z=XZbCYb)yux{zEue}25+W1sK;&Glo@Y=QWsNL2cW*yJ3e0u?gz0U$wFY$?a6%MJMA z{e_hXTApg-N;yaL(;oMs01isX`{^ImXd@T)K-eyi2OhXz{gfN1cELGzk+?FB9692? z1$@I(5TC?nwTW?$YXJ7C2Co&HS+D9Bdl*Pv5CD0I5J$zp&vK zUnlV6_R1Ms{Q5ZOHf}J**T_y_mx8xB^cqLG$6&Xspo`AqdqeY0rby^i-llwR(F^~) zo(kz?U1?YAne37`4s9xDuU~7PwKrS)ox1h9FNGHyb1fcGCAW~XaxitMCX3tnlw(QY z0(BA4OAViRA!AZtW1f!WaY8|J~)EtMU0$<+rRb+oyEjy_)}CPC&&qD*N$D< zc`ZAq+yrho9)INJp$sC>RjBD(!aF%z8vCwfx)jgY1#s9;k-L2~%v zenpS$;kuNekMFZy-k{70sy>O;c;$l6zeLHW1Z5K*%ki3=>4*AM1_ho1eNtufQc@0` zPww$^eyr=tc!Dm1*#ujSV$25e#3RSX`r3tTB*nwH;jdRVbV6m9!p7Yvf9`fdw>D0& zvZMHWjIzMmO=6_XIkCLr??K*t^DX1hfrI0s+9_coY8sm*>@XJ3o;^E0{E?41CVbj} zZ+YC4n4%6^h~U1lT;UACEuqgt zOSJVe7FEa?4vuq-`=WR!nc|^t{;rc!d<=xGh_3i8puYv(Tq$LIcs|rgwKwR#Xcf*k zMyUH34f)ZKjEU&MjOsKZOy(EHuT+9b>|B(N65a&#wR<#G^t!C1vd6Su_{GcXj9J5v z73kIgZzaaOAKMih!=D1@h5dVWk6-)sUmySPZ~njImfLO_yY^~sLzi!94}9Ckf&B+H zu6B)I_`iN(T+tZcwNo3??b5*058_8Z+`h@K_`03;6C@=8ZB`*u0KM@SFu&U5CBE9} zN7ptI3;N}>=G2kvuOI*5JO9D>q)+;!@vtt0&#v%k5!%&<%IHRK@`)ij9n0wOBZV%p zHjoq9@_>suA^Q{3o{Slj6${5i?Q|nE58V%@(HGbmUVr%C&DXu|?~Ert@kwK4ZB=^k zDe+4uP7z!)t*=`;NIzr2-Ba@vRu*fM6tg$`Z>h8TdxF71@B zj*;tymu=RLhaP%ly!X%lV(i_s&+FO6OBa1}lTWwrefGUNzg0}^lG=@p>i^jv5@05` z$#YF*pW{*zzRN(%#7Bcj_S2xe@$j}Sa;3CKDSKP0g ziL}6_QGp3xfL$wZo+>ZdEYk=_Sz`1ZC~LCdLYmVvwQ|o`T==CDl^W!NuWY)93Z^Zm_G)RRK_aHb2u}243qta$bpWYl2Ij; z0F$i!WWtb`>@ZD($##*8Y)~n2;beWqo25p%=*Alv`L@Y~@Z6j^40C(M@5yRJrIcA% zvnk-hGc+Fc^@X<=XK=JfHazi=Q@s`rOPH5W0eAQ!5eQ#oQE_1Z0plYTeSE)dgZA2g z@w<~CK^LdqgtHf1U|!7WE9zQc)fZE20qaO%8e^_1cRd%`XzI9UZBtqG;M*rvkYVA` z%k5KnDVz3ao52kLC4b70Gdb#XOh30T-a2WaidWW@WPNj6vFofkp{vNn_Y?29V{G5C zGx3utPLhwDI6lsvJLii)Gs;hIG8I3pv3X<|_~OxpD`T5-9_%awwwX_p@d1As1Bo@i zI=Xk?zH!@axA|^0*iZu4;!|oKr+feV|I+%|jIt@V9)re;9N~v?)@A3u=RePnM)Un} zhfMzX;#5uGkv!aBW8f_m-{qrOZWAY460weEx{o65-`H3mKk;w>?ReL_{#bps%ds;X z!73YmGQlyHpbYZ;O#eL;nxRR?aS(rxyBtdlpIla@coADdLW-19D(3Go8C@v@wz~jJ zN^U8mg7H991|L2Z7JL{WK1L~S)>FbgrWp_Zt`qY}wCN@mbJ%ZegAm=n`m18wkS8uH z*%x6f=5{d7o1a4)4lc5VD=-^4e6U{VRd&4bQ#kpWn|~xejbmO=Mn18Mne?3>{EV1? zA$p%KfdAkR-#&iwCx2=jI&|IGw{Nf9&9CbEt01_K57?00!Gi}hrr$r_``$kvyLast zN^=N%Qp$Oa9`X27j2H(9xtCzUk2oX1|GFvDoH({9qmTK)Bap$yhjY4sIdt98@g0Bv zyT+IPtuGztbun}L)G2RzSO?lyOxdJT4$=aNgZMNIV$*i<7mz<4cQP>YBavfXB+ne7 zjQ;|3pj)p?8@gazSs7pY+Ake1deMu=%4&WInmG8=Eq+K$%C~ABBcD%^9q4isy}=RD z^ttNPyg0CLpbh2g66kM@&7K*39`!m*rz568Lc6za)x{9!y^0qH*2t~8(0$u)|L(Z3 zdLcLP;8AS(i>GHk^I79&eh`cAF{6tEgG6?>=_0H3*e}}?y;etxi8nQHq}(8N7Zkwb z<+fv6bjJxCbktTE&P@vBlW)w(?+nJ!J*L!ee8>6WV~^+@MU)b2ZnXH5JiU1QdGG#% zzA23^$5|>+=eBy?#U5iMx$RSg-6t58rO$2}&`kenodIbP+95nLYH;6tU2~h=KU+>0qLPrEW&&w7q9F^Pv#a0-Cz>M zwk>*%(X>&}ws;i^8W%|uPRV**q=L;ND2FGsr1-A_01IU=KGgAneSaYOq2aHk&1Rhy zPu4lUckJ;kyzj^9Wk1E7F&T&sWP`Id1|WX64)8+xv47fO-{6GTJq}aAS(TS+8%J%Liup?uJR z4IqoT?TZG!2bWt3f9W?qB_DHfiU6pb5a9K9A*2^xbO6K<-vDBV${yT_4SWpp(98v{ zXl`#W7U+-KfGd?m^M_emf62pMr=;g`|UD#pjg`UKU@qp;a5qFQ~?&hh`#AA4Gst`(S_IlTJ>OJVt!z;Nfve z8)e+!7osm-Tpy=SpF)7unt-^Nu|P?w`;HnXNENM{*nziSTqLUo5v*)dXY;f}o5Q>B zezNs4wtZp}jlXX4|7ohcbJx!CzW2XxoOtw6;c$h%OgwtysG5KL<4I4vV?6C?_e`HG zbYiIyaG_>sC&)ya46-sKDHpZuwx9DniN_l$jexo{C6FQ4*X zp!sCLXAeBYPkgi^^L!%avCEi|7RpqqSt%$uQ^z;x##t`O{q1=jym_6fEnT+8)We(c zV7g1f)4!&bOqfl_nqBa`;ssJi$+UL+g*@w(^iO)h3+v4;Nc5^;J&FVCjBPC-J~Kv( z-SaGZKy(|>5tXw%nw^6ywA)){ca3?%2TU)B-sl@@_~n=a(0{!wsVPr=FV8x@a5d!YBDS=@1YzUS?RHEl9H`vjly zI+i~@Mw|e}FJs5dl13kG-s&INd*Fcw#yj8n4vz`+vW|1{&RX%QpYjTi0Uk}YaOw0D zF8IK@2B<-<3Xg>zNAbr5vjO1xT#|aXK)OH`UIZPYe{L^0qDV#@kc&JwVjB;S+oFr( z)wR`e>eOk~^JybDT5O){K;NjmG7cWtA29=M%lV!ZG`U6xgPdAAIX0>@X&0Mn^9vuZ zki=f|Gs5h&LgE%r^^Tdr@`92xa6W_A%t$I%6`c_+oDzOHW+s5gFK}6h1Ig)cU+5Z; zEjqg4X?6iB`-VUn4bBHp-5cctNHF+T{`tJD7musQN2Ap*{MJQcWho6g{|COx05|7- z0f>yS@gw&9+a{BZCBy^!>O#o}IlWTjkg`oQAgW{%c{11KZ7PD+JB#8YW5z{6e2M=; zu?`q3J@UIR`lkM=w)o-|Gr}WU)XIf0QmwEu4nbRwWi$ezYs_Xo7CxMYC5~bajDKV( zuY#hLFh@vDwuKMMHf}^R3FFJ!W-y6@X2PM!fW4@Vm9p}c~2lHcg*A5;R_GB z+X7zY<&Ujdkg-(ye7@jixodDW%qzJgm%uqCl2wPEaJviLD;!KPq?C>{CzHUU#bX(u z>Sdz`Bvs$BZhOVw9S#($Af4La$>4z#T+_TzNm1JXJa86zY#2n_sVsaN+)NVVILx`* z>62lSZIt31gKO0)fzmM-99y_E2g=Mk6t4%bz%t^?#feeI1<+kZm048awJl$`0Wc^D zImOgIpg6*_KKNpba#)&2`r%XJgu7dtGd_WdvCw&hmWyEfp?YaCos!$`3V9OZl!{4u zgu}k=bq@kC!U;yn#Zd7vyoDEdag?r{P+(QA6fuT-@P`jy=Zn28q$MmaHbVS$(L;|M zGX{C_!L&>7 z9*5DRv4ech5Ypi#*li0cZ4Ivwp2GOb7->G)&}RF|ci%ns>B1r3=Yb|3$y`zy5St$j z|IKiRxl9$V7wJL2NYBldHgaMw<^Ju9W8 zb%2v?okaKS(S@&A{`HUlYyaiRUVn-YC35`zKgyqCJmD;R97wm_w$y z*dABXQ8aK9zIX%GuCA$2ZmFCCba0Jt=zb%M&M+8X8fROf*+7E@L2&_0F)#n%k7(J% zVmqD1W3~tO?i&x>|IzV7KlDSsDB$KC7ts7A39aONt^OgWy4ab_slYfsd-j~hV#nXc z?V9Hrd@AE<+jj`c&u*_PM(ABJf&}CyEhKX3th!@JE}d(dTW40zkI(+h&l=zNecv|@ z?%(SR&~>e){P#9{mO?=`)2YIjUvS~a_@GAA%K$#n# z{73qocilB!_w`>dUY^9@Q+3F(!wn})NTY4pw%6K9WR&pD)ZU@-yJ)*TL@YHqxG53e&)FA?kDHB3+#(%sFMzE zxZqQ%H&8bY3-+meR^4cnb97d`B|ohzlfsS%5S;lDreC0y9)s&Th=;!8rVf2UtocDK zessxW7k2UR2sjnaDf|%F;X}E}i{Csx-T#db^j^VbjrZ8a7WHm3=1nLQB>)6H@m3Ec zmJ@(QM`~8m(0YaQxwUmq_7?Fd`L@+{01Kdu7Cz$;Xu$=u0nNPFp-{zc*;Y=UWn82^ z05K@H;zLTIFYxfWKLFu5r}_yH`NRz{B)IX+MR4q*TL;SJN5=xZ&y&i#53&Xd;2{TZ z{#vg*xWG}?oB0l=zVNdF&QX4t}%wEPt3`iNoD*)mxT@4!}8?C zHFzwjZ#?r|aVIEE@#IBN3*V7$TzUwc!)_XAFx6egdP0gXgM$-#^O8p=cx!1}*bp{m z3bzTs)rm_gys$CpRQCcB7FFX7_}N}2XWNQj418_yt!uW|wD1}w0LP4GlW!x&YTKsc z952VI?>KXu6$C_gtBV)4Eo;AR+l)S@EwLNi0$(dko9IoKb#x2_*6l@EbiKWKb2yaq zai4PZW&Kj0p~k926Mp-y9b-Fxw_~cXT15DCfKLGFbM#)}uSfXa8SPS$2ez!jpI9Qr z2DjovU3}g&LNc)FSzOFl9Lx{KjU*MG1GYqW9I5sKTKFKPS$6qf+x`3Z`NwVY<0!(5 z*798FonKvb+hR)oI2SKt*?M(?D}4MR#|~|xu5!?^uhe*C68EkC#qH~^JE99oz5^z* z^b@y_e)OY}lR5uYfoYLXg)ySGDbCbb8L1oRB);;&8(`(kb+9PCxN&hDK5}H-eDh7- zP%(a>vG}{K^!Md0{;v0*zxTbqfaRtEz3G0uL~l!ixBR?t@zQwG9ZwqfJoTw#Wo1P? zEYgeyUHo2Dn6>pZBQ}xOfrQAB1eDq#fqW(kD?LqB&HK)(v`WA)bmC>=8YUOn`A2o z)fYCwDK(#PtZUxj3rAo2@lV@<2A|kq4ZDY>`&)I^zVts_iUEOiO1ol!T{ z+`D&==Eno$NB-$QA1BY8_Bi$hur{5rMLzwHkM?^iu>Egl$4LhIjGPPw;HtzEu||teyOy@cHqgk9*F^iwoq$u8g`p*v#5gRufL*;R$R@#!oN>7&2uux^7KkLw{ENZ<6@SK-E(CR6dhnr##vi}yPsW~otPhL@Oc!Y6oM zu^cjq7gJKI@oPCZIp$pZ#UOVM{fXz`+6z3&}n9QQ-FBQ^^C&byBq# z`nIk7b(ZQPGoGzSqWFH|_@h2YGVES ziF{*&C%xo})-UERW5uDu8O6yX1w`xNypDeS77Kk8zp)u#!rfq^?V%f*ipr%|B+v5_ zsOH))^ziHc)`x)joGWodrEib}$x#MBKIJ^coXNC?R`Le%P5kI{O=zOzlJUH%YI*x0 z-Joa-+sVnV1yHlRl5g%wuT%4~e{ka?7h9m>e?#ldILZ^H_zF|R!IN@6$$kS&?1ff| zw-WwaZ_#s2f?ug~1Y%jx1^MhgSF!yi`I!)nE2~q{e@8~pjpn?RHpA<4J|xxM$HrcR zzX`TZ3#7mUNO=zmg)oEBou0+8Q|ehPC7Dce`C+EbVb6(+1yPw&sV^N3(UE}#FS?R+ z(3{P-Sp*D#$T!~7j1cpdEtknj)dq}v#*@*nAZ&EC)qxF zh0n$Pm2AL-M|OGAHm`&;aWYclLl%jK@T%T8=dC|>)iH$=FS*hZa#u8RnJn;Qz0%YM z<{i>4kIpXT4s|rQz(!eft~NE@_x_`700*(+X(4SzS}|6#Pf z*i3uNZ?^#`!{P}qcFEwO99jB?g%v-+rB5Pj)^30oLE&(gd<#p7x&7(lu08xs68$cE zEuyCC{osQS+6!NZxeL`67AV(gH)BNpYn4vFfJd4!p)#`I+ZQ?JR=SD|3uDIMZMWUx zO{&nU=a-RBojxNGKDA;4yImK_{DPzSvC5f2x|wV4e?%F(r5OLw_8mLMv17-^Lk~UZjg|Y&hKPa6C=&2#FN^o5eCns_B4wZY z{G#H{Bj5Zu5F2?u4VHdPXwgR2p3slVNmgauvaMRaV-7N~M;AZbaQTU!{z-p2&G)+T zk(051VVkuFMQD;ujoz~1qf^QNv7^nIlcw8P(<6sF4b!+1a2ih^Bt;*-hsR}9y1u{_ zP>w4_Hz{S}1ifWxWBX-1HRbHH!J5xW{Rk19`#}kVNM3=loitEyX{Rw(ES&98Mn-rVU37|>CjrKQ z*8`X>1)rkGj@P_p%es_c)A#|`zz-#D-$}dDc5a~j*Z=Zg9IJel1tC5KzAz47cVygh z>#e@oh;RPBy!=61pHC=dvs$r|PEucJk{XDC+bEjP;lf3Q3j&bhnIX}hVr{-t_tR(5cBYybn`sg=9j}qrB)Y=C| z9)Nz~!w|;m3&sk%Ie0yG4SkA}=dy71m=TZvE3aGl}T<|Ej@N zyO;f(aR8DiMwfNF9$#U%h=`HxWU7hi_qpC^9BB?f_PJPAOViJ@eET}%;qEq2L6*5d zUGjSI_hOI zcEY2Ybo(4a420Rbt?5bl0G@Kjs8~HUxv>*HSvTMUANwuOc{hVeKGb{&8}`!1mUmy^ zpK$nNTQE}=*am!)ADrhT6_u6`XJGQ78Sg6=cs^b58EmankJN~;R(Rw2KZdmyf=a4OXK}3P$ExdSfmjpyt_*zYi z;fsZpyN!B_JNjt1%Cv)vOTNS7A7K$Kn;#%|Yfqg#sW#Q83^h$~KlS`tGdK=e;9c_O z!~mapn@vafT!f|*3>#C~z4aFU&V^6c6Jx%!cI@GY$4U9X9e?yMf0aA(=%R1a@3!Jt zQ3rvuXv}K~9#68%rzlT;@?HMlOg`z&=BDQvn|F-^_2=0$XU6;9^Ilz4@C(t1rr%?y zKsY{8zVptz#(mFw{#aY(KR9VJJlg1A=FwE{hO5S7)qJX@*jtB^`wCAh2RP|dXYTU? z&jmK$E&f+O{;$T{e&=oezi0X@GW0LU=yW`Uhz?kSw@dITk0lUDxkzgF9oC57W0bP z`Yki#R7u{TO8Q4UriD1+CQ!Y3XLj2*cx*L)ZSK^^_KUi5=7D1?Ugjok*uQ7b`13#i z^YLA8c*A(;;fKbNBiC6&&)x01@bUU%JIM2?j7sRPiw`!HtP!`}e%sW)k&Zu!LTc%A z0q%uqiVuE4cie^ABD+}!Iwihv@N4XRqPtBO@bDSXDPMAfPV-I%R&?Qc^!gjd_rLkg zk zqEk^AQ?3{5L*KY)NE|Y*fGI|RaOqb3kPYK14ypJ5M7;z zL-NomaWJy^B1=sC3)FgXgYLuk-|w4ayLayqJ?Ax^5PKJ$a#qyl0Y!@ zZ*&3th~U2cdv&hhd#9z@dZmXq>IB_)0Ht`y97`?KD&r4(fuflLZt}0kbL>U6qk!}# zTVTT0vPB1Jg31g2cm*9Y^CU>O7orYn`z-TVFk`bDDzmKRr?wC^)*WU3iRq z0djCyq;fuX=P2dVdrKJx7ya1LqSy13*u;@6Su#3m4jcUCOnb4N&_AJSu zgtNSk^M;W-W_g+Fi4wu92X=o-2iZ0Rxib&MKxBZFUDKg;%^_%B5;im8(Cfq^ZDw%R zQXwcF>ZL3j#@zWcpttcklG33UGf&?$Ww8S>}=s`qg*z$%ilG z0+L3zujMU%OT{?~TS;H1WgPn4H@&FrpxS_!> zI^S`}9scgGKOLJAj^pEHU!ecVyWgz~+w)m$0mTFV9Y4$pC|_8+I9~SBmyV;?9myl| z)iG?~hzP#%DNNcB{iLZ)#wyW|eo+?>W7a%8LavS8&RyeYfA(j`FaOdnjvYI;`n&34 zu$}1yAUk=iw(TY1GT_{{qubFjUub4)X8PWASY|y)aSX1Z;~eWubQLOJK-mZ= zZ(ipqOOtbqg&e)H5gOkw1K`c0srfG5zTLaW@BYs3k01KsAMq!BM{l^^dYC`7W2Y`K z{Rk*fcfLIglshz+iMcNJG|q3n>8A0lXFbzTsPsm1>25z(&w6baD-IcrDLeOwCZ-QtV-uAX}_S}jebq`!t%vZI(-9A3?6Fxx~Cd6Lj%l6U-25jiX(QqKONeY2EF?TyZv!h3HZzrrU5kzreo zO}En;5-TwpKf#0}C5CA?J`3YDE%f;&24d(dojTb5Qg`E!t&bV!_7W?j%!jV<0_cR^ z3_$G2Tui9#7uK^bnIM416J9na9DX|tbemaZg)UI3&tJByGUqSHQjj=CC-M}#9puF6j6%qu$P@c zv6u*c8Yjv$gQ64PtNm8e(&9B8aIQXLPAquYUvntBszkVHvm3%!5}lZ*>6 z=zu+nEU@IkQSnK}1C$Kg6gW1HBO7klGO1kwhcXzH3g;y89-wJkwO4wvokvh@$uO0z zqrkjeNTG>4&d}Jj63?^;9)Mv?3KAcpXIcQEOO8i9$&s?84(SJq-Ciicp|5?L-EDqw z&|S42C^;%NoaII1gyK)*q@MpD^vNgAOIDjpouIwQu<&^C5Ery>&A6Td}@&sH}oyz zfd?OuPUeN;r#69Bq1sDDn;L&%Mkr1Kpln`cy@-1IU?7B)=}Ylnx_nU^p>5-7AM-J} zfZ)c4=q%iq_zzLV0WbM6kB1+AczpOn9~!$U4J{!NlPT=uWP?%TJ2{Kjwm=J?5< z{^_x{enA()+GG$1WC)pZeDZhp7!%mGLLx(+tW1kv0b-m{wg(gaDPkEy&w|goT3_=BiZ>AZ^wYfg%Lb9!PK{60yyaJaZT#bZ@=yG! z>Y>AjJ+A!sUiCOLqaD*(`x#dPl%N}TmGk&7H*!Ab)&IY7RC9m*;sxwa3k%UBPqn37&PW8H~OBCuhc^rnht24=^t;=t6n@;${Cj z^PArEJ>%%n>&B@^9~F%?N_zD&zZ=~4p{eY^X}l3j@nrnNlW}a<0Q?dk7l!!qy8r#_ z$IUn2=C8J(+QWs5^#Z(G6Yn~Ifd+%(o^{>cB!L&$j>_J|;-hGGRR@3P68*(%z+a@m zTPAH>aKr&@SUDo1(?-ee+__^s^x#9|UGI9gzartA4CqoickbMH?sK2(>$0px5~*=f zN(~;jQr>?Z#+sy~%h(N+aoW}ijQpUCjx8Qb!lDmeeAF281)9<5DqiwtEu7W+MOSjn z+K7!ujvX6o7xG9v6eruIJ1&lWd-je)hnO4mg@_{bv?X(t!O^+cfk)sQ=fxMG?V!W} zZ!-$)BX}GK4XwmYYQQg#@sth4&}%1V-BQuh4synlxy-ZKFTtc^*(X3^)E7>UFUfT6 zT)YSfLSE?MKq>vwY3hHy{cG9XhG{G`FPU&|6YP9feM56t{e*HQ`ktFjyLN52MAlV} zMaBgf{H(czyhCo&iiKo7o}i&mMc33$Z*jQcr*@kJA8{-nh4R4>b!?HGdC?cu(88SP zi@`MEtpuHBq_PPdW1%|**}SpoJ)sS-gG8t7$p2=~IYu^UlS`yd`q_ejBw(rX^a4n(1W~g`?QdYO}$~*9#Z8G!+$Itmlj71=z3Z zPYV^G)Kw1h!6>izAdA-w0(O!3*ShVM^Be>Dj%+r_L5y)g7g7HIJo(Yu90%o`z}XPu zcE&Ogu6U%}Nb%PR85bCq5#vd_6&YPmr!zW$0+;nq2suwJuU><+u__(mTrju}R z9@psWvR;0S870I_uys1&5EC{bSpa=;EtbB>rmxmFF6-iPecW~DUE}a|*ZI4Nc2z3; z$(h=|eJj5PO9yTnZ~w!$d*h3b{>~Dia8W^}>bmtb3p3|3K#NlQO2%hVn5R z!t{^31%L()*X85##tALu@pF7D4Q@Y=R3A8aaQx9b|9JeHfBkR9@e?QgLu20Xh}V&l zK$}P%f9bE-pJ;9i%*2`)CFX8x7)%2hUSmzGqBSPzB|e8pFCUw~^t28y10e+Gis&^b z4V6z-C1L_tyk(uJ&is^8O*=@)u;JihvozSA{i19=iLu*{0@`kXBhY%CQrQeG(jXqx zSl=do@DNngIAg8gab7;rgZF2D_GiY=|NPI7eFqNuSD?9Y<56B>5Vx7X^4a$20baV0 zR-MfjpCWJpd`WVz`TWltpYYO`j`NyVnM0EFn8qc>g_U?5Mvv+>=CgJv$9=sRyp9z- zfKUv*{_a-hiqJx`Uhdkl&0lr!jUX{>6P@1zaC?<(T{*V6nRIGpWxVLcA3uKJ%|9@n z{`8L-r%s*B(-ruJKNukZ$YDt3zQ7ZoB>Vs-sV`jE!o9*L~;lz1Nr2C$_?=Vg$aZjrd)5LQBkP2AT2Bbtstd3eD9t zI>&7nO~*I@bUXyMQwC_;L=ism?bt6ATckPZ6AYlB`%1JXFXRyE{t1KlCq~+8hN{PI z>d26lZUK?l@XfCH#@Jv^@!J~Qc(=cpc3VpZK2IEM;ji8(cI?Yu(c*Q<(M0Kq&i22+ zywrp9IZ;KMb{k60b)fZdPQvewbIHiq^dv#8Z#mC`M-C12E2zjv@uCgr3`6PyybP;s zVGkK0kk9xHU-qF@HXpi_!K1qMgqkj=#QK4G(Mi}z*-Fe!o*NROv7bbb{Rb?Q^|^5+ zDX0>@x*x2iP$du0H{`Yzp7@b|Kz^2lJ#>|V0PIH!X%~ovjK{lhjz@}s$DdY~>8Yk` z@EBl-5Ghw2_(XbwWoNlukqlSyIwQ#GOoIv&@1z3&*S#@u3nLuzw%_>TvwRYelTK(@ zENp77G#>-TMe7J2J3R?ir|NRcx1I22a5aB{<2B>v36lk3l2+NYrZ2z?h#hOM9S2hhL>PAiW_Q%rE2S?F2@?CeDqAOBbZ- zhr8~)b6nEK6Gd?IBPb7i^#1WMKS(7Xta}B+v7crPFSp*d^LTEQ}3G z$tvUv{dP(62M!(>PrmD}vAViyx=${m_XRe3`5yRRe(;0i*ok9#+|WEez~R}z-@0%Y zd}Cc>WbeN5nXh`K+rndp&CiQZx4|2f;VzrmJYo*2+9}{jA9#%EWQ9-km-|J`ngI; zl{(i8t_g1)%^PGeg7OU;p)GjJE||Uv@i&5X%+PH{#U?RTs82ZfdZ_pS9o%Mp-~s!! zB$cAr3V|a<-}R?}KH==Y-fkH=cqJasq(3>wAK15dtZ4r6`14zS<^LJG_v{%vcV^Ae zsJ3?WFgH9_g>TbYvr@(of8TatZFPL*SA50zk}vuqT@YOy7d7WLYCVhR9C5}%a}ExF z1z_CU_8(j&2xKDRt)TxpDg)cZ@gd zLih__^ZDa~E>!uBZ=R??0{tpWh>Iq)*bjoZ1Xmq#SD8nrPChzb^_j04pZhtVs|(;& zZLH+^!U>XA1%Z+;&HZA(S$ zPxz}re6X4k9i;H)sCvg1h+3ua&EuMLG`!qQF8+!QP$~t~3nyOZ5SP3jUr7_M$8CX7 z?IY*Z8D`zir4RRbD$agcf9U)6?Ndo*)YuI8(n(qR;m>d^yt8F_0phi0{L0%tqN9Cf zWKoRXjFsTb9Uf#{%FUKS8_eee6XllOE~N7@6%a^nz=C6Br-xvS&+M zv$iD;tTP~CUk-D_qyybl;YF84l=M=WA1rjea-id2W*0+2hpOdYb6NCz}jNi=L1Ck8}=)MCE ztERllp?ku*kj!9G+kzLMo=G_QC$L`E*`P#cx1nP;L6Ko^6(01wor*zVydZ5(>IHsj zKb2Bo2r+Z187nWg)O2)AGC{G!1`F%(F@ps#pnK=}ur z&9_gywF+L8ts8E9!q}yY%gg*2jc{zvE^4#>=%K7pB_q|^mdN%QD zwZ=*>_Iz@*!Xxp%j@MXNyD;v4@>9l3U-Ak5%Oq|xbh49Hpdud02Y)Jqt8&;U435&n zC65?9-etx-K8lZD9KXclnR*>KaBv(yeti7nANj}Q_kQR1#{RwhK+F!Ak?zt*=GZOP z9n)pUal$QQ#mxmbpN4@W=CoBlLU%us1Z+6551@;UE%*cgoP6xDf*}f7!QFgyV2f}0FQrA7fnXe8zbq>G9n zfAIrXN6K{gEP**G@-XJR_G28}w`ct2`~G6Q`TKuhy!*fX**JRSsQLLc%={8`d=Zl@ zFOlgCk6mdBpOo@-gHxwYkI(y@&lxX$=}X4h)eC;Az%3DLZ{)BIxLp){vDbip*1cJ? z<3*zEKqRFB#(3-`4!%Rl-S2D7$IzW@vwAXrACqo5U7;SLx!$j{lMmFs;UdTgG0U zk9>1NDq7kgTA~2p)4~qpqjh+l5~$vOH(Pj`H~at+M8|62Rqhewffhd2Py1=T)&C|D z?;39g@|1h;x&&*KpmX~XNH=W8JN{0pyAjc6+bP65ReWwRk3fy+bGP?o)`4~(OiLTE zRWj%-`Q%Ai_ks8Z&h(0{U7h4+E)1Haqvv z7N4iU&)OU__n#FS;DW~^R{r-l1&Zu^Zu>R38n$xcaqw$Uq|J5Mjj| zj`9UooscbKS<3N!(rczFF91|e!oJW!CQUE=B!`aXtvaxn#8-pOrsU%^;SGgzcNJcF zpA;s)uy5TMC5K)Y`rvDU;!pPb)2A#*lGVZgSxJ>X(&(54V<%w;z+RY;4|EFZK z3l#zhndpgKAok^e^0Y1)cnZ}9(@UoGdAza#UbJ`OX`C|J?6C&F%DZ>&@}tQ9E_1PZ zK@u|?s?(<)9qa3>*?jP5F^#m(($1%|Vs)6TS4cz)635H~V(i=o(gucwS(Gm8BH{3% z!{Z50xXBw9);Jyq<#E8j_{+a^+fdJCtGpbm!$J6kK0XQZCnfTi#~_J6j~??~Uw%=Rd4?YN`Q_;Sd-wUj zI@y`A8Cze!Fh2EDKV{r~*PY}1>iNk-9?wBe+ACoYMNrw0#uivpRi;AUfyMuIU7+*n z4q;_;&x@xMxN!fEKmQ-cFZ{wUs9*W@+x%b_%2C5f$bYA#ocPiY@@8DD`9h?z!-e^U z4Zbr9p0SlnIP9e!pRL-ZJ|8orYHEeOO3XWH_kkz zKR%{xd_m)q%cfG=4G;wK%#XQ^tzRH~>M2hFSU^+=uYt_>Ul|+y7@YN5o%F)ziJ+XC z5@?r_vTWG4u)_I&k=3RwsVb`uj_=R&6@&A-fPdvHUpfB%cYepX?$Cj8_Vg*dvVP>4 z&IbFL3Vt)6Krz?&GOEvvpW4Xpo zVq>(*tw+2rgG2{3A7@kLKZ?=I`P(MR+#n^$Bp}9OPvdH1{o;7&fd{+>CaT=vyren4 zK0f6YuNZsw?)ML%%}SQa1d}6I)0ErS2HIO~29!At_L2C;HvQj=yT6Vi@-#oa0cd`h z)8@vp?uQT{-n({gAFC_p$J%*5{l}-!eL*E_nBq4Z_*w`zo7n)PC;KsZ!`#6qxEH!( z^D2;xZ|)Xf^UppOXwT^67UL6hWvLH)b3L@^@&%Oi@#s1?e6fdq#;;=sz}hw~#v$Ve zuwR@51^g0n_*7rE&vkUTQu+e)2i3F-D7y{DFWON3mw2?U@K{INQQ-M2LvH$Urt(b* zjYay+PcjiQjTg^J+|&5js+6vjJ>}^0o>2*VSs&o7F|RnG0q}6bCHoLs)}HdmeBsU4 zm#PhypcfDP$Xf?$ID}5od@A5$&+F{rp(o9NtJ zAWAHPsXSmGtRuX}q1R<>(+2{}M+dz8r5p3Y?F8p|W-sS+ws4`LgZ5NElnoU)2uohE zb6sVL^_)+G(4mTw@lhUr(R}k?{p+zWv`QQ#R{k;H?E*3Z--y3lwhG5zbFmL!#sNJ5 z-A<7>X3e+;S3}M@?xYT>2EsJE=7C{wK+^%P)qXTNp z7`81pL#p_RH>x+UA#uIhH?kQQ=(zk%5YBmmK32YbFg}>jqjPz~AwXNiV;s_y@rzoG z2mH|_E{e4RbV`6(a}_m7>?N zv6!Ce)ZRXZT#zh^KZtnM;;mb_U`qC zm_O;4yw{FNVN&-OwxFYL7r(}fZA0kr*`BI}Q3_9Kh`$2s>?8nP#n1${rw)mX{3tC; z=ynF0Z;6lplRYrf*P7ZE5YHMHUD(fhr56n=yc2qRL@e|hD&}qjb;uqQ#e+B*15O1t z0{-0q;p@aBD)WHNzQ&UT`0npN`Dg#!dzV884_FEE-Bxd&AzDghW!@7|<$NTaJmnyv zaq`6R@$#3wbbQeleZg4QeCID@p!Ye*-*;yN!h9&8wLsdW8SnEK{UZuPyFc=d)2A@N(Ma(w57G1f5tW({{)-@fK+zsi4)#$(WCh-(6TAw3pQ8%V)TpHdX0 zZKA8Xj1BevPGRF6AC;*#t2L|QHmFJNFHjK7N1ZXo#_@{IL%YWFp7$KzaN`Ep6|Fg^ zA3Zsq_w0Mei(mYraY6Xm50pGk!e@{F0{0hjOP?j`biRAjO9R>@tc0*ukvhgqR+sM9?oI>NT4q&r5{FO!$mRcDK{*EWm~Ww4;tb( zH@EwI9T1*2E?KEKHidLdCV`0-a<8?hNxOMM2ja9hEOWgkU_Y{1Ut9{pkTO0cw}Ny? zC8~*+$B|LoR%)zsnEy z6tLNzTy_pP1~m_iQ|#0xx7h-c2k$B|>%JwX(GlI!Xx1uDBu=~X-nE95ta0ZH6dRs@Z(K|!X94gru{hYqe0g%6?&aJc({6u7n zzlWJFt+AtiJ%4W18?{#C7GWPAVSM7Z1Mw(wE>4h$TEXK2GKi5c+q+rhs)Y(r5r3ke z5|7w!88_Z^qd&ET0ev|!Yk|?mfln__XhSt!7@(tUc01U_Obg9pAcXkpV&o9DvgG(e z_10T&6@62WC{nEJS zo_of@0|&7Zu_}MKZ}C-#55u_wwSCdMH>BsDl4-hdxZb9f5xt6Tsu2 zm-1{@8%oaUv5;oBFU4d1DN+WX`s{z_OH+-X{ZboBr%Nt!z|WLJg{#YHSM#E?Pp}iW z>*y=}>L@nl>>*4m``dSH8wa#WMQa7v2+~8N1 zc@n_7tVOlL_)bLjCB&fZNXPJXsg#%PYlLU&Lxb6d}7y$ta83Yp`at0#i^M|37wm-OpY^|p62-&r1758U zKxcCCF^{o_=CFe_F8zxhWk$z`u&t#F2e5I4@VPdu;!^F?a4IhmkrSto_& zYa8GSOh;!aMHU9zDO|0K*aKsEQqg&8%_!4Nu&m|%<^@A&KuP*#k-}Vq&9LoTzx~_4 z%VF!zAX+N>&Nm&O$R>y#@ESDffR^ig2D)p~+wy>O5JrMo6geoFr*hev#W60u-YkF+ zrFdGEVUo+D3gB}#xg}eZH0^LnsTYl?puP!=oSY5VcEzk@!y=ppZ7=@7L>3*lQfI=- zQ{x<5;S~LDW2$waEkcw{19URs@OL!^s z3(*fh_@Eyz`?q_UP*|AfZqGiY_&{po|<^tou{sZITW5>r|f9S*h)E7=aD(*N-M*Yk$GM_kp zVm#^2C;4w?_>m!0$yr&$rz_r!^~s~h|Lsq_ZM^S&?;9sio*Fy(l}uc!HlsUp1Vw5G za+Hn3uv_S2s_+#rI0JU77BlVN+nmKaYiIw;dKk zf2`MYorFa788-cj8xxP{iL}*W%!%I+;HF$GOJ2A<$+Bm>B0nsal6#HgE)D=&&I%mzIkeeht4$QA--*(F_@;n6qq{(FEAn2rz9+2%Y40PxBn*&*=E6V*MQA?5xKEA4Tgj^IPXkj7 zT~z2E5!j$+nJc>R-8KH|Lx1JpRNyA)43T0CTz}-cam!7&)S4D=@GI*Yc5DdkqGYX4 zo8fGr-2CYuKUrgzY7b=?Tp%N_GT}_k4%{qWu z>UAAFxNe(}#*?M&C4bRpi9bw{317FDGBlubLHP|JGv73ooQmhpt&Ft``E3-&CXYe$ zSBzf!us7)pUMWr75!qFs)I!9&!B20A4t8I>}bYR!b9D;?(U4kB+8a4dI`RIV%I9m5xndKE}O>#S65kWj&_S_5iyy z_$7BmYmHJrG7S&D@{9MA&y~C;rSX1o!|aFO{JsAWo@+3}wr~BmZ~Lz9;AKZoWoJ5c z-H}#EYhZieQGg|xpm|&=U70Kq%OsgLWWa*gy1im`-IP)bKFpJk_|)Zw!p+z$y!acy z7o3S-2Fon;#-K|x4k%oginf`hapc|JnPKy$yUQHmrOmnX+qn3-01+H}cuj&4IpI8! z!6C+djf0OdXGQ*W^O81;@BQ=l z+9rQr!bXr26S~+O9^Aig-1F3@_+lR%7lnzp;^Q1u*mB8rAh@L9=@;2&@xw>52t`Wv z4<0-yU;ccY)`ht*6!qel0QvRjXWx6Tm};Rb`$_WE7dMHS`xdfc^H|_z9wo=su}XCD ziH-IXj$S|B`Hpv*$0ukrA}(3gx$xiw06G~e% zCkzzA7CWkV?(o7PJLLv)bi3Lgk0ro?!hfW~ht8CtsZLuRW9s;0ly&j@1OA~W!fHRY zZn=!ktOI-}p6}|v@Z(-E4j(=|-tmsN`*BPz3T=?SRogIjT5-Ak*4xH+e8+c;JqPxU z3+op{!{>V0uDDCsr9jt7v{Cb$wuyfe&=wlNJTj~NBy$@9<(hxQ+i@!SSr@*jkt$NN zPsl(+FaCPGB89Imc%3E=PrU7k!37pR>&7SdKfYuxTeni=&0UFO@<7@jUr6EaF=Cwa89XHlGDn(avmN7=@%5ME z$B&JT3+vuL#Agv;2kNU0E$(q|BSK8Ju|v59gP-gwkBW+~D%6wO;TY`L=nx#4X`PnP z{Xn^8#HBvqD`B~LmpIe5>#n=b@yvhvvmWZmAi*Cn5m#9Sx3kKPFTc_!sXK*O^!P~G zYYK}Ayx@#C+0f<40q}-%sVh0D$3lDy6c3qj;APo`c$Q>#LQSL1Ym9x&9EnZBQ5s!` zE$oRS=WW(2VxF-KT{-I_jPN+H@I{6>L_OoZ^rqlCg2CjN8HDb_nlG}Ax1)fvSq&8z zf+YUbmCbWT;321Ssl1TJfoS52W=US)L32=%uXVBcUdZUj5@-A5) zJi((R`Vj;N%rP>Lk{=l}FTcus*^grKNh@~pgG|v4u;G40Cu%lT$l6}nrLN0pq!u=S zjK{}-g;)jC25ug(VRc>X{9-M?0DHSOHGI#@n|svAr{l+tjnk*{qho%&O{&~y$|YU? zU?TCYs)1VS>&ci-ht!F@4XWZxj*lQ+rk*}Z4nfBysH z;)S(*zstJmYw;_%Y)H9S<|O2CpmbiFoxAS3Ykcx2zs#R(pc7pgm&!STDYZTHO&6&` z`7XNJY=RJJi!@Wl2JM!8YVOCJaZu$ScRP6Kur7$!#!vsde?NZoU;gO$&__O`&Eqcl zm>Y5V|IUCfT%_OQwshyBbmj>j7dV+GF1!H80U6=!m-*;7D=b{-t<~*uDLk_+@{AjU z0@NH65WgC`lRUOSluhIrQ?!XNWmF&#UuGNaGxJzg@K%8?a!TD&wcW7}jxmWWPXuIL z5!SJUhwtES8~ZeN7$bl12Y)cW`wibce&ttw#Xkyn`0ydAqdCH-fM4^~Up2Pw*f!3uu1XF;F(){J#GM;4tE+3S zOF@mD0@3rbOVL5u^+n&wk9>j=e1Kdu;r)qv)Wcvr>y`B>MOV?GO5a8Kv9^{^F!6~P z?%-2EK7AJ;8&%Q4_wLWHT^OJJ*`GbW{ae4yKcsYqAIyTx8llA3I?(YAulxG(gqv<0 ztKvrq8d;y|FaBTGVC4YqTDA?p(~s>#{H}ITq}*||sN&=RsLI49X`VTDIH>t;0B?ct z0+T)$z@tkTD_XON1#7(7{DU{~FF;Phz7Y$Wz~zkn@Pw)R2Xe|P zh!i^d&E*2wK6bV;4sl-^3P3Ea|sLjvWubc;Z^xf(T>((4m9=+J}E2 z&=-x&ks5bVX1mL=9eL4?FJ>smlJ2W4y26bf?8dVPTMfa%>?i*728bDuo%@mw$rj4mL zM6X)Pn#Xu)e%ZDjLHGYWE?Q69Y@LnAM`a#=$tRv>1<(rveoirq&1Av3y_FYrI*+pk z+J^U5;kUmfPYj^jPvf9R4mvo_za3ZFSd>Z}#ngKA0+;htc$!WISikFqhY4BeJ`@iG z<3LL<>#tt+6?Bb@@MgZJ+-jm&63S_VXtbkvl!=m6l!Kh47`al#i z;u$s#EZ(ubkQbwES+s0hDjU`%biKr{g4SzAjHTh~IiNO@Z(woIm?W#KZ_@r+7j%LwGbS*mYolhu{o&NsD zd{ONajjGt^v90y>e3EK^!eHKp#3nJCN#Hh*1z@ve@ZfrbDT#?G3q5!ry+CrYPL9u9 z(D5k>K4O~-FJF8~ibp9=pFTUzo?Y?DoaXr#IK2Vr{zNC10DBR9`9QJxj8c)d@GHtJ zk{*L*y)rJWuaD=8F@HY$RwMpl{A)o!+=Z*uqNWd>*%nb-XlIpfbcQ#@wFTr)C z!rKLp5o9yIdP6`zdh@6Yju*V(W4)%b(L%pZD&op_X|-k6xOnvR$?>P}dC%CjD?f6A z8TXNFt*_^MQN%m1JidE&<@|WX%U?d8ci(fzg|+kIt+|ISWt`SMzId6&iGVR29N@7) zuDZul2Bga{>S!uC7f<-iBWZl9ws+6oaov&Y$6vhfedC9Je<~z^);yH#j(YJm-^4fa5IF8x*E$p$rt= z?vnR$+PJymvW+$rekn7Nt*gqR6ki(+F6|B@9`~lj{uZm-#=tRK$}zpwvFFFs-t%Yg z@sB$Fi+}!q`q9Co*I(}+GlQRb$q%vZ;0MW2!hF_T+rE__%}OA0qiRbogvG*MZ%r3@ z>)KF%@fUvK_=>OiGCm^nyfNSt+UyJdVu`q4wq5D~agO75URjsvlj;jz!ZT}`6F`X@ zpT2`D;PtQ>N>_4PS5z<^|E#gK?KVd ze_-7Cq&vpRM^DK9hHv~3pRfALuNcq0?|J@?sr6f%tV=KR?(FGvOh>gNv&%<K$fU zj3t^GzYdWAdgPFR*TMo@P$FUg<&G1rN^Gqk5I(kAp8n-#isl<*p~ktbU=!b&d#W?n zwW5cr`N^d{>lyKy)weu(Azd!KQB@Xiv(vQp8D%~9gVLdLkNrt6tnj+P!8n8XKrP#i z{#Hku`Oo&_$4`vyo(t?1a#IRE&I5?@M2ppy8vliu%4i}Ij18};yy!cWgHLAY_1~R8 z!IA-^zOO#*Ls);6Yz>^o3UgH?4RqAD?I^W1Po_6RY^>n`hRAZa5dPbRKB? z0yw+o@o3iKN6zln7^|^@55zZmh*S9I@f;12QKHSx(W4?%6`=DYY}}+vo%w&+KiuZN zt2ncc(KajAA^0B0b6e3D->8r#N`*kkDHh4?ql)NvJ8UC5eS~hPysIuul~z}f4@ZnM zOX*c+^Bs>)vN8Q7X4O3g7HgsVm9lVCvxE?*mB!79V0kCUDyrcj`8?TiKvpltkK6CW zyP3li4FSgt66nIG9J#3R!8+nY%Oks4rb%S>O$GO(;^Z~cL>)U#b@Ehu6d>Pf842K< z25akMtWLD09%80)kGD2=4K{;kSz^=SR^Zgp)QsuQXAm3c&??pl&H^E{IxWR{U}oHc zY+fc+CO4;Fcr6kYhI~4t#K}gyy)ZTSJ699nZ_z79o&^ZJFEp5J${7st75imS8Iy0q zBja|F7ES>ZegVi?rg-rIowbMt-~osISzc1*@;ulL=(1XL(*BB_56tjSpGWtx}1< zub38ez&=+j7$Ei`DKRqFj3+C)!G34lWDHrI^+h!Yqtymv^{w6^RhoByiOOv z#DTveA@@t}^2sOdIDPW8{ig+4zoh_IY!Cb7^k$6OTo=e_ldHucoy26@_HbUQpSWPIAEeY&M#>hD2v4NUUJkMS+C`_A*Lz-^Rn8?{HO zv#HiN(56v)OVQ{%x5%)r3-NoNdXFEoyQm9^bW#2@nB@QQ6dxB5{NU93#S4lP2C%J+ z$Ci{lc1h^AO*Uzl#k*sC=4X8R*tci5HbnW~S9l~r<~Y(SE?jeQq<$8vB4=KWEV1Ud{@4Rd6Og^8vaC@$*FleP;g_gGZQdKVmJpIlu}zadZj zqE^S&BXG&%RP&X24SiZaD|bIJ_Ul*D^^SYs*wn?IyHxRX|1xAzMH1CMKvO`77jfs} zb-@VsdbIm!|TyurJ){f(se)a9+fBTpJYCQJXqh1tq0?PeK_WJ6tWLW?+ zUUTw+2_<9AsgtscEA`G)cGL^Dz)u`Ku6BBIyzQsnI)2~>-{dR2eooz1F*y*Mem)-9 zOUZA&8b6Od*ypmh$5GXGc091>Dtb*jx3Fv_lD?~#G=kgT_xF7FII4ve;~5feS2cE_&%RLF1ZC7zK8NtL&AxJ3>$qgFQ&d(rjx1jJ)^TfI zl(y8kb}H0eq051{m!cG@Hw}JK7Imo{Saam z?KZf<$?;9fOw<-8w0!YXUe_^ywU16R9i+-fx@bPRVIOH+Y&r7^mmTzjhaY~}<1OPA z`H@07Evqu_-gV*F%owUN(juQe^Ng>CgOjh{t6+P}ROpU667vc-6i>>VN&t1vLYmhq zNgxj%?I{4KJb9xoR#g7xEjhvA!-vN4V@Gojm1xw%8SZ>Kdspw%<|Xu`3WX zw23ZWxs58p|wiDRO-fZW;We*tGY;3J0)>ZAmbl%iKl(6 z=DB^>D<-M^Qh%KI^Z-_N&E->TM-_GKdKORTOB*s@$5ThaW0U!@OXGEX)4XuZc;tQAwwc^Q-cTKEqV910<(x-I;J_T%Z1&dsSZ@a@L~gHu|CQT zEw*uzQ#1hJvCr46;T`W&Bra-2NH2eaqzrs@Z4mFqcJ z34Spajl>6tsUftpM8ok#&sjbZCSO)1qy_2^vv>)ugD^Z)YBw&^U116d&e7W_jimB0 zfV065fVWU8-LN7rfpN;P;5DsvgV&~iwZDi>Y0%Rt+@KnYIr=6cK`{~FTj&-PUjAyx zi2+!phtPZ_FPQwgpf!ZTfzycfw(36Umx(hJJ$jQD`+1VUR&4<&o%ol71-Fpe4@vY7 z9ezGjj2y%WT^}_d^E@9q45T?idSp|Ei6MIzDhHKJggRaHSy?+_WqN~0gtAoS!)n_r zUgBISJb38Pc;JBt#=7uw43LALtv1rZ%i#0$Kqn zK=KM-`ax1Wl&emYcjDHs&2CVL>^g0HgPW5N`<{Agy#M{bGv4*ica3}Qx!V)>EnByi zoYYANlSld%Z||m=^X*r+A@qttsN0?Sm5!~@d8yqVwWXi_>Ayd|?i;^h99LhZebGK+ zyKJhqPe1V0MCtO?7s{X{Ui21-zZyJ!aM__#P!X%#26*iVXJXPyNd8f&a-iSiTllR~ zn-@tf9w(X?1~Ay+1sqrZ<&D~u0}e=bn)ERFJt-gXNwBZ~x>xz7dK=}_fAUZMiBIn2 zs%Y}>vDV@$2af}=z>dKvC*$ytvpM}=qTJVf!Kb za=ao?`qn@Ies1&5V;YHP0VN6TpwrLWRx6pd25{1VW!h}>M01exPgQR|mUIw_t2`x( zJz+s6cDGjKQy0)3ah!f}`0(NJ-~$iFb~walX%Mwtp84j{5|6QvQL2rTn)!+VM+Es+ zG>^fmYaZP}g$+PYS<>yn;2^%Ref*S;FC)VSP^ZF6ENSgSfI5wCx*A|<*}>DMHg{!lqvvR0Sj14OL2W+>w$`KMt-kAiLCMRv3)w2Vdzj1?a`G((ogp=>Yy$AR*JNH*#}4KAZhA zr3yrYY`*4&);1DVDBBT_?GVH7MZMBJ^p^ghl*5c7M3*(w-f0BPAQG3H z$7J-UhHR2{ke+)c_*^(|-=V{D4_+#YkyOx(FXEtPXUBpkXI{e#iHc5~3Mby_ZdjHN zeWD2n!WWrlnh$w?@kfiPM(NhT>m{%kc!Pnoyu6bC2T_9Mri zyjDT+dIJ}4c*s9CLUpgf1UwL87wH#8pt@BptqHiZX1mhO`8`F6bcJt zGaMNJQ&{Jvv~(t9pdp_!#ey6dIJ*v)%@E@GmQc&pAi&R>q=N~1-VQA}%GT-9Jx#n~ zKvc91T_=Fj?Jou~lVpuD&g9=hrh)fCEzN1+JJb=E-n2<LQeAOFgD z?|a|tNdmR(AL(ap1js0~pQrL9-F0G`{@Sp{ zXFknBITQ+VHkYfHOy2YtLu`jpKzUg(J5eYK`&p{Wuj?7W2ha>|LzD|<=@8CaWSwq5 zf<5Dxa`9}_zxx0FZ>FtLoD4XTfvv6o$l)X7#v865Z++`e4c;z$x~{s|Hu9y&Ay_W9 z4Br+@J-q$berKz` z3>wcqa`m4p+NYni zLVWZRCIl{_gsXcvQ@R<3+Wu*bs6+u{g?W))$TecIunNqmy+YGbE>uj|VmWXLm=j^z zDKTF~fDgIQd?g1y{LuE9A};>6RXjbB*JfXtg)$HKVIHfX{c`2xv?k~VjD{Cb;JO9e z#*|AX!3K1E0_dhSV*(=+F9-?PiLcOGWA~JQ3#M%Lljylpt#nu@h{$}ios)6g7LEAR zDie3CpqG>Bg#wH?8RUr5;7FZQEbxt7HuBU2qm)E%hf|p4nFzRQ~m;j%hNWChr4I^jNS8Yy>*{7%W8HiR0;~ebT|lApOl+`U%OG z6R8hqasQ0UK%Q=Ta^dAyT%lt?PCTAE&A5^~9#m~JNQbpJdtubOJ8|rHrtS|Y#a<^B z6jC(&nd3`*8=ditL4@`>Y26G0Ag!E@yV8Oq!b>CRbJ(_>F^{{MRM6xTUs-qQYq|;L zJEyBbou}g*w5fia2rK+1OkkDP8Gm%!4UPO4GS(3k2!GO+IDE=orU)@T#Mx$|3iY39 zNU&#@I-BNw@`;bz?&E?@~&F!5kl&+qV! zlh~9V^KzUsO~XRgSCvjE4%*~37wr)DbFhT9Klcm&>=#{Ec9jMOdo&I-xDuG$m+uHf zOJhriBT2ESU^6R?UxPgI#Fp{|3M!68awe`tkHv?UB*Ymlg3wbe`7K^BGMj-Ja^#F8VdPe#2c3`fq-}c$t#z`$cxeD(|4KmnG8Q{eQ z^l5?ZW6Xh0TpKwxo-2KnT@k~Cm=U{~cw(P#+Y^nFP!=ZHY)?J)#Q5~5KQ->d{nd8Y0zirAF|PC+o+Nyc_bs?UqUBE*cKjc(K zOSueST0V&GBo4TuAZJlf@2WjHUI|j~HjtR);h}ua%zQ~}J0S;)8KKdSHp)+&FyO8U zKJoR=cfND{?(hA#@x?EFN$ZkzUI26V2tHfGl~=brq+^Teeq@6BQO>IW-0qbzMJ>~u zn8tJShmRZ?uX*ij$KU;XZ}VrmIDr8_?FIv@gsC4zEDOOpqbo1$NghD^Yl2FGo_1Ht zN-Aw!7<8pWEAQAhQ3oC=V4?}L&Zz;FF3Z6M?gW?1b*;9?VhK^1>Rk0mUEJUDHG z{zU$KVrc^SD@b18(Pv!-@@$^k>MBjAnTna1UhO76S%7U99~&mvNb0`mvcG)>U@JIO ziz$7*7DL=3e}~%A2R`@*vM?JYDc#NnQz|bX>ufJ}!k4In zP9sm{H|dj{Lwv0IajlUIhr;;ImPQBcP807`{{fO)r8m!L8BTJ`tWdbT@H=$qsK(s; z&Bs{9V=FNGq=)o!jN*Ip+qP}99_wyf(NY;>Q*2A?3WPuT2__jzqhFW5pppebCfr)} zBhTbZJEOgE=LfpzhaQV;b9kX0IeJXxJ2bUl9E-%1mt+D_{7esio0Uc5* zP)A)Mwy5l?1p5VEGfjA8LXJKs6o27@PMbNv!Ah7-GHo9lSLt~p^p-7~U3VT=OAnr- z&m!M_fS3@+31Nk53G)&cbo#0;)_`1ih+!WzMM`c-bJPHBiU?xU1VU{If8?BA2@Qp| z*doP5=u4S7f3)F|V$kN|dV|MIi7&$T36MT%0f&=_!lG8Z5(MCBf5lX?QssEaold>L z6M9@JqyQ}SNX&^T1F=M{%Zz}>;Z9Kd<#_ch5E*Us@2R}dRATF>_+*^)2=~}m>U%5& zGOdc9=dJ{w3t9yKzkjhCK*O@3*`s#2Hc)%nDFur6!G!~W0#8N^B_rrFQBwsM&6tzu z6rku&de^8c6<+WKJ!l3N24a(xl)S)XJD-^N@|W))2lpQs8@ZAtA_p*+UuEOj*z2#m zc5K=zSlDG@(Uf>8d+%RJsWZW1<{5^%jyW`%S!t{TB; zetrl!m*h0-GqdBgTQ8t2%A0b}_-ae?Oq=Akx{G)3_Ckg$7fNuR_>0L|>Xny)oEirX z9vm-z$xD=D^2ClTO1SFrv?p#{eI+^e@qF;pW6$mj{aom6S~#uM#3!Euv4VsGo~_Ek z0wOA;r1fBre#zCzRo%@W-??2%2QPYq;496vE9;`nTtVXMVV-p+zbE%TH9q$7PmJ4d zzuoa&yLONBw{Q0%ja$~Khb$U9cT|%bWzX}^Jm+fLF-7(w(cE+Y15bZ}gs*wtvnPQb z%S5;Cy3!FJ!p|7uWKu&1LCQPycMZ;~l>_e*gDBFrIw!N%x=4>Q{b-T{7h9XS2E5 z`!xAwyiU1PCgqK*>{aE{{vz}^tE`V6IpzuS54`!!;|G4=`&C!#ecS$|hni7AxI*S~ zuv-F*1?jhxG4V7UBDFa|nNGCE31pf4g}nxn`b3R?A}Q*+hmkrolYp{-qeGaR52R9U z#HZ_7&1#@0 z%_Q$|l4$-T9}0*$X9L9mE~)~z7u6r*!iPTer{i7kde3<9fd|Gtci%Jaz4yNH{O7-L zY~HddeYwTKqgNVH3b1F2cUs3~ zyVJc>Ai9&-6|eIF5AWQy;Dw-nl>vtS_0@9fVDD4=e239m##`95Q67!~^T}oTgtA*E z@qoA|Kc*cSY-@b!w29tE79Ai%_)w*CMFx6o3|q$CsWKVkpNTydG-3rMQ~v1u1+-mg ziKkrNAZc$=BFdvpn0&|H$1k`PS~=vJ=S;#x6|TU8rp`*H#c#Z>;DFMslGljzEB;uvF ziT2yXutJTY{c2pB7$OqAtJS5vvq&ejEfZt6CCX!3w~wY17O!013h`Rf6cnu^j!FsH z_;C;+YdrU;w&X#ML>MFGTB!6;lKk8v_*_`~^Z$%zf`O{6M5+P>Q)@^tg)>s9b_@9c zv=C9}tp?I;P49-+4X0?v0?m_M!2GBaDd{xi(#t`HEztn73;7AGgIxnc9H7cpMzNH@xw=&@M|ClF*{z%htNsfY7{%nvCZ~7u<4uCJRmJ#YPqdE(#oCYb~>X z$iL7I1)bdCRKJRQq2Sm8OjuCiFVpM_;jSCv5Jls;Ilg;)|AP;VOS@`Ds|<> z8ulqQB9=D9H;H@DrLe?Js(Ln-pS6gFAAPk1V>Bs+jayE4Ua(UWm%W~RZdkY8{&Szw zB!z_~eq^!Ct$Wv9ca0`Ad&cQgydZ)+(@vdr<>6eVB(^CJwUg_vy?PuydTiW%_uXD7 zcR8^Kex4trZKXaaSL|y%`b8_9K==8aK;ep6w-fY0k8c5AMbSpwy0KLUB_GkxyA&LVclH}G+_Q$9Fd&uLcP z>({RL#NQ--u0kXQ5Pgs(u6{4NRq=z7e@&pKaRCwhDLb@&D%ny6+HvfHUq6F*v&a|j zy3BY;U*Spzrve^&@S*Xa-}}Dt+wXeU_{1kZIgTGYKDKY)p7f3@I!r~ilXjoQoDpo{3L{cvS zgi0*d)CLVlEg@~0o;iUD+F1b^6e`4i1!TNm@D;UgAKZX&>giMNHvsQZKqjB{p}x?C zzqDDk;@UE1qD!#57aC~l4f$o1Pua%k(xX-m1Co5>* z?Jx4Hbo#mbLj!1)DS3yMK3Y*^^>e<`!B~9nmme7Kc*i@&=8c=i7PYI*oAda}Hoo6} z<4qbv>T2*pXY>+ai2O>voo@X=FnmS*++&M*)?jNGc>I8qcsJZ|y~l@sM?=OFu{iJKgI%$V zHsxp~dtdy~Y;ZY{%?3kcgtv@?XtiG#z)3+hP?Z7s)F9n_9=FdMCr_O8al*}86x!Ij z4eQ567hPl>NV#2#e;Tiy%_N`@KPxPIvlSa5@*p7xq|c&LIUEs^x;8j$Es18lXg`G5 zzHtcMJgK|LYcsvtg8*KeYdH|5;hd;&G#LoYhyn$?17V6oSeDJZK%)zic_kB)bD5ya zkVpbU;YmS$VVLa*o}vYB-=H#j$&>Pupbg#n;;nVU70$j%UO?(LKswYFX}4 z3~bP5S#PP`kP4;)h5;mc*;cVa(Y|z6{xc9yS{hi{)?~MoG+M~SP?4@z1Q^|lB0HC@ zl@vIw>G;IL<^|d}9Vescq67+^1tAR01UU_|0iMLuIXJuP+Z{xV-JlVG()qG?T)aI1 zCmob9e1?)YR5>7}Iw>a+P|{}J&Nn=>Eg_d~(p0}3l!b&M-gP>FbHE1Afw2}M3Ztvb zP#rWqdxp;1(0K<(zU?uiWUbeHt!GvSD``-$l`>>9-kF4#+bX$o$2Wm_j>_NA)gQZQ z`;TdIf)Ply@3M(T9#IpXNw;jXTap+u%)zb8%8Zd%P|tb^sAEnla5b;Xj!d|j9H*st zV^?ZoBZ#&#&UR_T-CXU4%*Nt~8gVrgjj0Xa4SwabPC~m05ttUmIVF%@4vB(w6H@yD!bHrp*#F}ZZMYSYwrJmHPplmJf! zy^rN=s@R&4QwX0x!+PnT%A#_t+pw<0aUx|pCZ&Pb- z7c-f%B9&XRRIPv5RX!*a{318kp-7esbk?CoK$?ZxG7?PA9ZB(n7sR5c?Bx@16HN5N zJs9b|kw0JR|e5yHI2JX@DtCJ(>8oU)rp+USu-Af z@IkSKl1Vf9GFC${nXK9v!AuMWJ@p(8{MCBcENrS};VT*^0K1O_f~W3a?F3{a!-j}+ zQ9AOT9%#q$lkdhq^2nn}vt0DhS7ON{cWM&#Efr%ad4Y=`9m1CjYTwb+0B!{h%SidE@IXTQh6LvWpQ*-Y-r{qZ)P|53eENB; zPy%(&+zP5&lL~Ru(u4y9U{jo(bu8k7 zwk-77PINbKgK32W$-l-vQY!8e3QsPMg-*I+riY1)9T1(fgTIJq<{0gGZKNmBdyXa3 zS|G{6SC#cSI2ZDEXuM{}maB{dacU~5Dgl;CXYa{VRbnVhh)mMcFz6nkCw&6j08%m& zZRY9xsaNBM*cRG+M#SkJ_!j4)^PPblbkMp zPqs4=@Ly#F$Cm=(o;X*cY1+|-c3rS@eC6@S#v>0u;wMchR~R3bFFyO(+s4N} z{;~1sqmPUonw;`EtIeCYjP>ia;6aCd8vmoetIKam=PW;|(8y>-dri6UkJCj@9Y@}E z)@48kd+!QyLsxAIck607FH+!-@4Y#BZfi*JY%Yrr7WSLgZ`4A1oo{)+6p{eOKsmoy z^5TadElXnC)3~t7nF7kp9~SqCN>gBel879)zQZfr?OOtK*{C-}Qjf7gWm3Pu#&vat z&vIr|-LF~iF@?Jw+HOzg38j;T1!Lm%*WV!BeKLT3$`BNLfw^3^3yKNaXd8}`Zsy3t z1>%GdsRIiaAIQ|U9FkyWE8|YDdBIk8fuTn2ckh!=`K|Aq_~Q7mUgN`_i}v{BPIMvQ z%Q!>w0XjaEU=_SSZ$*8n?5DcUSx^8e-YId=5{h!S2mP7 z@-F^-u10jlxnssM!qE*(YLRKR1zm4}$eBs9jT$kFc8)7>mhnORBX*fl04*RctLXHU zEpo)I-sw$OU>f!=>jMk`2U70DwK*Ao&N!RPNK|{JDoA>00wGb)uF9QUK_*>h@xC@Y z!HG^qjudQO+8ccVqm>q4RDUiyNnI!4)-|>B2GZi2-~`f@sxO+63EXy-KG7Amw07bS z%@CaS$b89Q9>N+UBI!LFy@+&|M@9uskl-e)KxLtwkvdJF71#t~4xwQSKwD7Ib}V_% z=0t!U*7_yKEr^di^3eFTU;SlI)_fI96B&HVRk|({Z_&QxrW?nP|M*Xglc!IQ)4Wj` z-R=h*NC_!jm1fF^mhsFuf7_OE=UsP=Uw!-AeT8__#!dE+@eQuD$kJKkIzOl~=kS;8TB^iF&G|VrmRMRUc1FX-o(>SvzR*6CRqz6RxV( zRZw~_;|*=iwtH-YyOm*YXztevVb3K;e21LMsxq<&qU1J}~oxx{jKcxPD$F8du;QyvUO}wWuQUDV7qrQ6?|i z42eFeBAP!zhqeePY+0c(vh0G3GNOkCSlS2qyD(MO5i-2h(tcr zS#*;YmPE4onAoxc+XAEL*f@C$du1DMi{}MO|N3A5+i~E)0l%2e$=XgHKR)*C*){&b zKlqukar0L9L#sxe5Zf-jJdWc@g5r6+z#hrZ#U{rdpW9ajG-iD7q{0hDe?nwrIdz#- z$Bn7J{EVx9ln#0Fab0l}4el4f&z&*{4;>kIeDRB}CjkAlN877Hojh@3Tz}p5Oi`g9ZQ%#AHXg`@wwfQP=0_(BnQ|oBy|QY{8@v!iU03mw7mm*m1u z@jxgDrDXmFaH@D#j|nS5nyf6bM%riCi8b{9fYM=6dX8P8+SZzHcms$E_sKBQ7q;j> z$r>?j!8aueDt!f*woF=;u6T5zhqP?b3!cZ@h-ZEo8p?7+7azwe?r@<$k%{V>;SEmn zpb8uU5{{=F#LemP0pBPy%5G_a7XVR^zE%)rE1-Qc0U0TN4t)v5a}InJ`bwXpH)HNO zK%O3tqr*IsCB|G~(qls9BmXf3asQO7L$daSl94e<0;P(G<@?x}eJ=PD zNk;4%cI`#&sW6ZlwR12u8kh!7Hgh5bW1%z#5O%6)It>*v)f547Lh?u_DuT8ptdjAp zOPgDR;w$o{BZb!;2tLv#-eo>)@Unp;&ptY)GLW_?uX##z>PTe+dGhBV<%W%|@R$DL znD~p`&~`Ho50ymmOmuWW3mW@!rC=g1!Fhlz>E#n+wR7}YwaKdWdJ}3?jU2hnMl}x#(g)=NF%7g5nqR@K#7( z`~)%iWCI7V-Hp%NvR$#T$}k2Gyuw`8x+S{QaK@a4itS-h#w3qq`7S4S$ex1%ewM(b zjMB9&@ST^>i*UQ4CSaa~nw5zo6Dvx^#@YQdV}tVDwsrIP?RUR(eD*V+9Xqz4?-Lwi z_U+@jB9{sK@gqmZkN)tFju*b<#pCGlqsnekCT(SbyKeUxFXCkbx3F&8x@r8`UwnAH z_dV|(TeoiU)sNJ9c->lra$t2R+FH4lDg_7n^D=CR`Tzh9hbN5+^=ENrCLd@tMREOb z5MrSWs>zE`4>KY}3;is&eC2j|${u~Rb0&k_y3U)gZ@B*Yam5u^j9YKLbzFMsrT$#T zMlB%8llsOio{8oSv3w#3KROQzgHD@;Z^%P-lMOb?AScyq^w?y z`p0w5Ssrs>%)$tr`QGjmPkd#3=}TW4k3IGkZx226pkD}wO}v1LH}oRsYJ*7oBo7GA zx7!(Z(a+*1PX00X%_0gL!$oQBa?#y>h0?BBfMe%(eb*bu8{hZ_zoq=R7T>N$@$zyY zbRdB3^dHPf{b^CDzL`4}U_uDZ&jzs~03JSygP8$*Plztn8b&~XX4QolpM)@GPL2Y% zBOVLjeG_K-o^6Iqg20I}1#=7cs)?u*z+Xz1v=w21Se3x>%1F^gTtGd$PO9u_t4kgW>90_K(md9Io2Ph{j{R=l zGJn&CP2)Fy^Ebv{f8?WM$NA^Wca$S1Sx+20GXCyQ{Zz)7W5+EQsJt8o(#9g2t5L}~ zZctkJIwp%qS%@>aHV=RRp?2oe&gF@062V&_K6ig?D3$~&r@Y{p{@g8b?>+a8$Der8 z?KWDqmlD=Qr_Y}DN!k~^-~~Ccj2^Ww-Xf1*e4-X00krZ8vhWSgoqSa?wgV8|a_r#M zCf)e0ebux;X9NhBT>3D2RKt*z7wv;PY#w{;(Xn^$zOkOWl$1t4zxa}i#szBsl!ZA` z%8@rlL*ou0AI~~ZOi(~H?JQ$4#GFubsu{Z-@@p%XbRh_t<`klpP3z#lTJH*fma+0Lc%rM)Js#55pke#D?^vWVTkiBB|CEY+C2C<8l~!oJYg zNetqdoC1;zoxCJe^2${)-nPqutrx+O zTMdzkT?%VZ3oqpYput9ZcKmB+`Xjhn~imtQ6|+)A8@u65GBv~T^E1*}&AEIy#D z@!5Ceyio9BM$+QRiF)*DG9qm(&XC)>dGmPksjrM*{-s}%IE!bMRf|AhnG%C@65sKo z$HtxucaNX>nV{o_wQ^e1EM zwr!diYT<}n*E8yTL{Ny*Dhm|%rF11lk|#BeC?_%Cp*_1rm4EoQ>?DH^?LX4RWfp4= z$r+L)8tEds|4A3+LM0Qr)0&|2&0$WK@YyA*9z=3i6#PM-d z3r*hW%+(nts1H8)&^U7Fh!$O^JmKbQFSj$Vk?-CAJtgid*1WLkNn7wjGJz}-Y>u6rEs0^=~HqDF_ zc;vwBPx$?o0b8@}lq#!FxNGWnl3spm?c+qCq~`ka&S z(2de{J>HR*Hu>B*n@Xu15hn7(0qp01~~?iOr1pkjZS7{A6W~e*#+@1seM#UtE(4L7EG`B`keD zp#@hd61WdpG3gM(-}RI%|l8^V%?lc)HyW4bja&6SIrNrJ!mR)Sg2B~Q=|Gx*=k8~tKh zn$)%;ODeks_;^-kHrR9{j(%16YJRc3>V*vS&bz^OX=i!{#nl~ivR6RRWmilaIGu_- zvLG?L(;4^`DgX0xW4Bn<2@&JvAmglbmaxok6)?deV;^Nlx;H@x8uS_IdXDakU~ z$s1eAlrS56z;)!bhE7SE)o6$9d^!T1yqF6v4z^67S*ZNC-~DgniN_yz`inIY{Lb(C zuJH0^?kZ1Dnp5ofwjv4P!H>cdqk0)KmCgajle@5*U3y8SeA~Bf9>4Qn-ar2GBOmbs z&XXM$G7>{PS9G5l$BrBw-}iUEcf9iJzs_&fcAcmlabk@2N4b23%eN@5wH!2VnPg$K zb;~9#1Wt~(zy0mw-h1vH+jg99`_CgU?6QFvE`A7Irv>f;B9R?Egoz_%yKv9N%CafF~ECQ4jRXlUgJ)iR4+@0|)lGZ9MYWW4@*I(1C;F{x9D@jvP7cXM7K7(aWTW zzUqaqwmj2Mn|@}j!@uD6hg*$-oM~J5kB}>x(7cXe=lY?qVi&l)mAQ@isW-+I{DQBz z)${1lBfeVxJ%9VV$2WfC*ZZn7bl!;TT6FtPTbHzL>`L|oLAu;71hlnW@lITsX+w(b zT~vc}@~>l4SG7b>n~f$NzX-xO=zK)vqfL^2~xq{?b0SM<<7gJX4KL z@W8>=Q8R?~U{2$6n)7af0%INr6*^6uLQcw1X(6}WNn6U}llTly zd_&m$9EGKWHkOS|Ac4!W?v{+(5QlWc(BP71S4^9%ahH7i_IVND&WV@BurnIMBFVdxr6UTttF@MSB z(I}1sZoS0uC@UPjy^W=lzixB5nw|O$`c6? z%~GPb4QZs|f^6afVwb=NrKGkE#N*fGZ$K}(D46_!>5AvT#K02!tiW<5+hvNdf^@D) zH-MOem1jfQfTga=bc!#)3W5fxKa~NWyRK!U)HA{7xxr&6xIInj`f-5cjj=b~a?9WY z__<9ld1d0s1ULRjoh2jo_LtiNF}CCjI{OB`h3)n)>7d%-Pbu<&Wb#Yr72Q!8|L~0C z#&zq)Z)g$BXMr|xCR+1?HDjF@rCg=DK;`*fO;p!wVw>lJbx_wLV67&lEEHW=6SUs} z?8lCx;X4KPBepSU!y+15VVmsI!sI>gdiS{VOLvTI+qb$6G9moi-}`sQ%U}M=apL$< z$xyzzjP2)%=DdRj$;4yoN5axhvgoi$SR+67q?PCN4({7Ge(9HfS!F&m*2+JrLrJUg z`XD0UneeTfwv7MrAN`MG)0WL%aG{Wiq^}03%-s4p5A@2+Hee=;yz~6s$h}WIK7Q#} zet8_wVr}zQZcmS$*gl~P-w`LsL{W7i`WY=aa5448?fEB9pBWE7^swJ9?1dB?yv~=l z9Gl#3&<)-PTW2ajgwSmaOq>4H6IXU<>nwEKM*S-pnPnG?m#aYBLBPhO&@}lT->hGo zmx68Gy48zdu7vSe0gF|(E!(zwF^xjrpv$wfC+T1MangZX-A^bye*BnaPpCe;c$O?D zdNyucKh|l%i%~q=EpMjos0XN=9aVx4Jl5bOQ0H0vVqj*5GE8|rqC|Uh=g=a2?FSmPIWkz@nq6V zS?0Rfs4?d4zxL~X^ZFhwbfLRcYL5pF>>WQW|GfG&-#VRKOP(z)fTjXlqYEyKamV>k z&RS>!WtVyAoCf#^p+&EcRV2IoK;>D-K4g6iGc6oRSKtgRY<-?P5mUe-_rZrA8jn2k zh{g`?iV={JWLhuv{k&VBH+F2_p*~S3pjj}&%*G=d5wvc6xkx0TU`Z>y^HL1DZG$Wo zrcp1(p;MktkKP_1O>}u-jvs`X%3U@OKKP)I7k2;C%133p_L{55290f=$TJ43oDq+| zqFbA71TV1vU?kGM1@Ld##m4c-Y_SClJQVP`yw;Z%>0gKnm+4iuK;>(a@ILrJWt=ph zLdy}wHbn^~*B%da8KAMDSD{%fR3SiJ%fc0Tq`kVWS}wd(TQDu<&0{mgTY4jF5dk!y zGo9mxJ_?c!(Ni6 z#Q-AeI^?1G2J;}_J!P)QGS&X?47wt@N zkkDNz3-@L5iStEw4M0>qxs!y{?9H19Aq~b6ZN#NVdnTr7V5C7y<7m6A(`k-IuW06M z8_2$FqTK+ICt+cm71KOOL$;Wq*xrD(!dEu*Z4)L>e4SpJ#6vN`;Ux_@LoyelO<~Ky z-Q_JU#S2b!>6-$llLT+10LP1-{Nta>9 zQ@$!QlNmE=(CMo+mPZh*>~pm2B+uDabY-Ax+f0YAAiCQ2VgiJwbgf^y7+lpbIBRAN z!hK~$`nGJ`H1_V@>*pbPF%wrHTo!J*RrQ@XeqvmC)m7vCo#$)eU&Byk=a2>mzilgf zvm-G9;4m~_QH5X8nAl88)1G$o@sEDgx3Tj47|#a#MN7*6g)ex%CzWiGMvbHvO|AQb z%Ry+O$X@g%FS6`h8w(8?a2-Z9p*jEj?Ox>Gb@yFZ+@KYx$8QN9|u<1wk#7vFYF_1sEC!tSBSU zSjHgyq>_0uhp)MknuQ;4TZSi#7x6kjuI{e&tqUlFKNf< z->gX|`EkXGThaYCY?lI`=d&~T0y|k;$1iaKKzqT@X)|mTn~4fEcvC)=)FDRLC*?*@ zc!i%ndD<^M;zYo=zVlD`+L8x*Zo~8(6M}gH=yQXDi?S+64$uTbdvch(&-0c3`|iDW z{Of=HZ^nIJzJFYB!A_qvu$UCc+7jfYWPH+Ti0{7f@~?T>*uHIB7Cm)!4nV)3Lr0Qw zbr}e>b4k?>@q^<8Vz+PLHD72V@LvG3F!N`Zz7<~m7j^E?yz+x$?5BES{IdW!QSgc{ z{UbbOhzKk%eEr_wW3jal+4sONVV!TcEs(cb%K&yi!k~ zlqvp#p8Q&S{1d$GCytGTVl|CO*RgrM0nnAd8qVx%Ji_9cJ5h2`z->o!C9}SCsXVm9+?A)QgaDn^3>rH9SWucFJ@Ox<8 zX3{31nQjKjOHF81Rwo8pZUTuU$5sv=J{w^Oos`IuuR?GUqmw$*F;Roni4!M%(vjna z--hpFfIVNj07B8J6AXq@`8#iNP~0SV+a4PMZ%4yB(X@+vu`cLM3xE3|6cI{R6qiS7 zRuI{Ui%!sBdhu~&H4|~prk&e&(kH5)nj%DO>H6#t)W6V)CU84bLh>pa zYN7Kp9shtAFv_+o4y%+MoM{fA)((sggK(cCerv z-i^RcpI~lC9R`ZOMOMR7g}@E67+rB5M8Lb%068cb6o#+k@Xr~w+(etwvqd%&INM?* zc9^FVunXBrZfdq62(C&EUw z(gTD!0L>tpli?%N8n7z~NF4#iJL#iy=UE zvsD>Z`f-U1NN@g%ht{A}k3dqUI`bJ@vaY}fQ`yF3lq*!XfBtsAA-Zq<&a-Elz$=Yg zSGjeQ$<1^nP`25;RsLULGdS!f!KaM~eubv3>n|aE&&ZAqeq;56T9|L}i=sTm7$=S$ z9WQ?Ai^uwnoBh12M?w2Hws25Fe_!1Ji^@*7di}}YDFsU$8#Uq5gxtCXS6*@X_~IAu z7)OsB@pI6;*a>-T>WM9%Qu@l{kB^&fy3uz7^a6;tMgvTc7?hXU;%64j{fQlJ1-w|k zzVeDI#^*l&d0$cF3MPDB1nD1(*e4E3c~G8Pds*D34*78sW971!JU=!cZO4WzzxFf4;GFB76VKkxdohOpSf$m>IA88 zrHe-S%(H=KayR&sOnfS4ixyN{6mH$7&Fph1Ehd55jI_$V)X}kf*M;NeTW9d&R-S!Qg&gNZM)d+Z*oyT2hrjs5^Ibm?; zop+A6zx~(!JU1tV=!WO5eP$dxd~9q}dw<*8{;qG2_ME!E zC$4V1;RdJSH^xTVNH-t)@fx)?kGVdci`Y68#xF33W^no{Fy9PaMmLwGtTLGLE)kb2 zh&S?N@lF}R_wIdaoH@<0NollQ*?Q%bS9)BueWLr5amb_JYB=`ASBg29%M%<(%L&+u zX`m34?&h5#{fD$x4@i4xfa&xxBCUft11I$6dghq8f8Rcz(BtuwL)y4|$L|s`ls*Br z+a&3XHtnUysw!)j&pfl-tOBD7EY}GM&n;(COm@<_=`)laD_9hy-@B;B&==du5jKp`IA$rz{Y?7VeP76&q zf9us&SHQBP&d9$6r}CmQ6JtN?V;|88wTD&wJd4KnLP>$wb>h69_7!5wY9r+N)wwNb zb5!Z3g^noMq`rc?6@e%Wy@g|oqmB!lHz6Ces)x?kdK6Q>v;*r_oHxtzyerROQa7q0 zm07a#AK`gAz;SyQlM*kEq~Es15r){tK~xFkIc?<4+duJfmjSfWO`m<>um;=fufNWA zGP#2Fy!C6x!6S!l3um9P-ot5?izdKrfMfw3L;Xw}X;MTBasE94DN~*eNH>qlds^+C zmsP#)b>HqQ(eyKWj{c%NGNI%7+V#Fo_b>k9&nN$qpZkz9msgR(h}fZxtC1`aLr+-` zYoUM5b=QvX`P<*)$rWeZNq1TGbJ@@)-nfyH#fF68AdyKZ3&Z{U_K$bI^PS_7M;{(P z@s=MN|M>s)KaE#^^Edm&MTZU_@|EuNb;(li5_dZwkI7HMRWK$*r*(3{j^`S zX%bxH8g5$>>&#f$j4j^N0u@uzF7<2C!c&uKKl)qCkx=@aY}82M;dB?9Tnl|yj+){YCAcB z6khVAjXm<%qvP=5BOdPz%8UH6z*4_Cb7t(h=pvMB+>342sWdnMni1a|PFyw^nQb?L z%JJA!DTE+slCOMBoaP)TAf!CXPi-#qAY@3R;VE4@6PIdupeHK(CF>0G)da3olNOn0 za#BuZ_SoX`DA}_38bU=<)EGapch9ar`KE-6&0U%3Vg3ncI#T_ZUOZ(!UFQ8@uaL`h9X88oJof z%?Yvi)I8898;Z|D6=+j;v0bjG;sspZ3ZtJ$Hsq+w){$cnJ|*3W;k8fD8C?@iPDuUG zA826FG4(+~)WnZILOKti>o#_Q<0rll*eCEPcU&$$`dj5;rIbg3r71fk+Msn3A?Un- z(4B6(6>Byj9rv9jwm&>T(wlCInUhxoxM+zuj~Ex3?kC|BnKFtNe`zx_fR55-{p~wW zn#H%-Xls$-c$y;wxV8bWBz z*Xf-`XOV+Rc2YMU!fs^HmF|jCM6^`5(p=HdQ%Uf`?vUM5-bnMAOY(HjG=OfnJ+Y#* zAWUvy7tPwkYhA?)5Ex_E2O0Av&4gw!L201q2%A6%GBPP@>9K^~DLW1v(C z;Kg-D0OV_6QOxZTwQz{W+ex_{`oN(B(z|i?3KP1n?S5GhFVErvC(nhlV0+oiUg`yD{F}o(rzIv` zr8h1LJ^{W|F!jlEKvP&BgmfsgpIF459hY2k@p$}+$H$|OJ>~@&^^y|`Dy58LA;19r z=p&E%#b|stm$&@l0bd=ppOT+#)JDkWNr3e6V?x0*r+jK?=LHvx`?cuj8DmeRB4~asvKpJyooo^k1>qOCJt-1ji|o#o2@twGp`g08bA3{mmdlRZov)}Y z;+-Mtnh11%h)E9_TESq)%5($roPAw3fWb-(las%)Z zH5A<`3ayS9ytE<3d{wl_B09`n2Q1>&d13pG|MVZn!w)~?wt|v8HuKClu>Zh#t=bGH z-FV-GHCa9Sqs!ZbNAC!+vMaXTh zYuwk}SCk(`VnNI!4)@-BZwZz@=VwK(^IhsA*Is?~ILmt{uvHoI-TKOmL!8KpIRx3J#LU1Ud169R|xo+3K5X6z$5N>A8$e`06 z<)HCv*REZ@vxW2(;4H~Mc|@-y)h~L{IYY)gv*1@EBulpK@m7ArIyR?-A@raIi&vb$ zarP4rwkeXo$3@;}z`Gw1#OzaQ$6L2;_k4#Foz$aym0f?HZ<}7r$xCNM{wO04;y`Gf zuW_@+*3?t-PB|9kvX3m3IKFV`%ne;frX`Eg(=yY}yrAYSoekDqda)KAnAU7dpUh*g%WL>=0D{u^6ew8$V2+=1N^_kXhRqZ#Rc-W)WJVhg| zZJKC?nKo0GSPC3}u_Ydvc??3jHK5DmsFKdY%Rfos7tZm6BOTJ-U{HIri-dbL(_F)1 zqJ>WWWBi-vt^}V0Yyaub|NJlF*{<9)VmzmKRYIVVI1{i4?1tiRTnR)`N5}7!K+-)R zEMz8h;$G605PNNEL*Xumx6mwZlCe5&fVWLBH7;nS=GR7)bWo+W9;eklB<(zCfJ2Ln zH8)MlEKeTrq7RYQ>AbQbH`ANA(l*jlU%`7TlJNisi$W&^h#ofcO3tE{j|XvV?m@@# zKxKg>0v^~nQ@(HCzMLI*J}f+*9v5DCVWmfJ=jFm%UjI^<0J=i)r3~u+Bv@QK(}1Pj zC@Hf275OF1gE~5r9=XnEjLlm%sSF3k{rBJR+fn@-p8(r&16MeAU$}c*tc4&~Y?u%u znn5NyqTI%=faJlJw8~O2=MNZD+?>jT7jixJ=%eFNZCokA4(vL3@X)yFrklogUYx>0 z*gDX?(1+u!D{TcjNv0TqPg}%RK?qEmf>IC9Xi>g#oWEoH`0S@|vw9Y`t&0Va7r|O2 zaP{`lM;{q4deMu#Sk7~fD zg^8(*H=JaGCc9B3hgqjK^6!J;U3c9%?z#7#am7_vk87{IeBAo{TgOXZ_BH-&5x24O z9IkJBZ(CKz_zhr>Mqi;YotQb3M!v@AM~efVNHZtEpJYr$%~&*{IymHF5|^sTQ+SRfBlhe0}ydC}PzTxZZiW%iYP7-BHPiCxxJq-m8MJc`c ziIPkj$@b#ajM%hc{do7g-#b3>sZYpf zyWE#aW!&J=8a|ixlW+Y=-x_{~zFhJcJNuzPvws(#QBkg>~f4nlWy<`DUL~_IN3cmQ{N9 z2lIQ^K2S_~VL_KIZAZ8^C?qKO4oi@{&;`BElKUX#L~!k<1G6AP zlN@;y_nA|!ToElA;E65=6a)IBD+5jW%0l63y}n{0c3+VonO$!LWnNPBTerq9mSS?; zivzA$?$V@?&w?;9K)36MJS0yR>E%{qx^LyPVkc^o&oF^9m|i}@4}!KgY2p=`{8Oi0 zUO)_{XH|&tq4}I_rt*=1D@{xyKL5Gf#(Ez})B@J5VSyhzBD@-);ZLp{n($||fI2-cz4(%G`DK@lFMaWgeuFL(NnagZ z)E|JT&A{LKxv$&zWJ*oM7rZQL|K5G$lb`&A&(dFg#g$|G)~(})8*k8J_$A}|>#kQG z>&D}cKR%8gJ338l@f$u)|G`H2RjRv<#slQ1IQBaZ1A+M6PKqv6TBc+|u7LY{yJdeA z^%Vf2RlT`_nDUY0TgqJUN~5dk|iVTV^V$s#AD#RgV)}-0GZ9`EX_a z$k8Ld>dT!I+?nvBKl&r%d$a(4{_}2;?ls~$orR3#vBJeqY3IEMg2LI0*X4zddlxd; z5MPuW|K@F;vOiu9p0Mze1E@>(89(tQxF)+EukZ)FvmSKv$(QZhw~V8QkBr~?&3BFW zyzhP1dA=6=EMTc)|Ik;r=-J=It!B#H`I2`0*s*bw+TJ&O(>H}iPUZ8IS75sfw~pYh zL$Si0V|D|lV6dd2{Ti8;NEp6KepYb3fQZRI+ap_PCQblQzSJR^keoL!UgNv$zyE;` zjz9dvKlb;4@tMVB6MdWU^sPVj*1R$NB;$tiBCFC7j2s|>&(VMsVU%g%cU=gzORFwS z*B)Nyflr*&jHKc-JIlazm?Tj@^qJ79u_OdIS(3h)H>opLKDBS3@9aUX7eoTLJIV39 z^OaX#F)q9lVatX42CWW8+WV}0g=peayjNrJy<6t{?o^M{{ zGvBgDEE`+Mo8->4>@qa1@{OVeKl2dUbL@|lZ8<0=?Cxb>4#^!AI_Ea-Fsh1$>upD~qpS$8|a!z@bu25YLbHZc0)J_#6{@gRc=R$6WHsB&0nOGV^8eFh;J09-zIRxCoQ*x z0dO|xm5Iy11}TAd+@oK5%ii3kfDd7^5=99qTOHuqM)-_ZChi7^(c!bun!qTj=19B@ z>AX}G6D&oi1FL0(gE&343jbkdQ@lTS#35a?oNC#{!DUyvxVW?IV0FEWfCQ z*2$A6#s=SdD;|}{O+YM^>6Tlcr!uZHj!pSQ(qzPB8@fGlEfaiDa(UY(`V2I1(K<9F zWY1f+KmYm9`z20m`vp-_!8aJ&I;o>MZ?X_}jpFz7`-Sf#|eZu3&!dbGQ3t zURP)m$_WSB2QNVT8ZGKx@{*V4E$0$@>Z!fH?VklbnaBFHp$6(RjMeeY+`C-1){J>vnUYKUAE4 z5`-D?)_>g5`vuVRdwVQS0v$uVI{K~JreSG$_pOYW9cp_{@PGIPVIq1uR zmL$_)q-!c;Sm)q&CLqq5?h9x82&3=afUCS9hczEMIJ*I;9k~?9u%*I5oKKM6A>8qt%rW2_hm9xL2C_RQb-J5Lg!yPA=8S~bwzf*qX4;?(nL_e);WLt*2`bGj?bfFAyYUB2kGOzW&T7G$rO=ij9Vx;vIo%fJzxbOK`LA#Jh? z)>(s(FNky^+RYCd8u2BMP`JbaAAAaTV!GGYdMk^>B=|pIo(k9^ugb@hzzT_$XC0Io0ysPsW4Evcy)&(db5j=tZ<{kIY283ViyBQ?-4%#0 z_10Ah^CdC)L!hTAz5Q9rLPwhht@yL`wtb=bR;Uvv{DL6{B)r2}KMoSRFS;lP2y`QC z*}^4{jg1qaFWR9Arn~?%JPV)$);SOK%&aVelP?P>CM}+fsC-QHaVx1Cv@rUzCM-uG0i=yC*L$6F>V2NPGgJE)zRL_`2<`Xjdhdw5ns-yg_yxIhp3Q}>I=$2M!V{b@gr#xP42Z3^*S-Uv(`_DK!c zv6+SE_HA3mb#~nOr90&_-c+g@XA=+7EP#14@j*=hj~zWcUi5+&PG`jNXC4?C>0XD0wY(8SMg z>=n+pdDpMsIPUxMm&fg2xWjL>zT}ciY#X|H3-c{E-#A{ZN%;$3_=0iiWtUkAxBPKZ zg6A50(PH)Z-W=VAh1n)-OP$~=KQ`c0(yOj(Ll@;mfv><)e)PJnB%L(!NV9{^o+Y(( ziQkK8ZRqyxmkMK3c&$@;_}NA3MM}xT^`nhEpmBRDzRn4*6TYg&o4?=ihVK|}e$$)A z>t6S_#;wo0*>`)KK7GdRFt?G%9_+M{m{l}v;al4_y)R+nBiNN^FT8|VChZw)=_jD- z8e{E46j>`N@fY+etHm62Uf{^VLL%)%n}AyzX?qCpqrP~N6LtNc-}hg}Z@%-l$3cw| z=kMf7CMRKHi_iTcha1%{Y4e;Uqb?{%nJ2&|c+OhSi`2H>^ycrEU(R@Oj9n==^+H=b zZF{qrz%C$unS21<@$!?|TuA+)6Az@k4dCYR&miATc!x_Ft5sa~g$fRxkTxm?;|efM z{^xe@d+xn&y!}7$Cg{8Y9XrqfKi?vM^=rOmyzcei;cr}9PGDQDmUhEcQniF0$5sKX zE5}rTIz<8L-YH(nA=Vb3KrdRe0Lr`D$^pv z`z+7)b~|*-b{1#7_~)(QTefZ$UT?rwJEZ*ZDOP2P3<>Bpn+dDH!5b|PPV+Y?hzi5w+|1@?0g~^~)mJQWb z0*w$>dT;PMPh=|D&`9%63DMGd0#3$rqOH!?c*;({P2aBkv`x1{OWtiFX0gI3V=Ad56~g*H_S zQSFjvmytxG%~T*fV-z%%XQ{+C6s`MTrMnD}trTubi9ZCb3mu~NA~WT#{2)yIzj?zm z+fXp!k#p26MKAuj9Df7AQ}!&Okcf zY%Vd(4i~Dm^KqkXP>`mO^8MTY-*b!L)v)&G|Jg76Vh>`#Tw%~~XeuTZ+wKR16BRjU zaA=?q0PtDHY@}D%l}0!p$YvWR`4zO%;f)wt)8N9}dcd`H$MH^k8r&Z^2EQghWKG;`8DoY0p;P6@EmY7|QGB_09!_ zp`c0VbG#Be6eK-7rMSkx=4rZ99Oa<@)ZV=?3CD-$`8KaTd-ll2Jm-dDezP86q08h> zOBu>a!(>-t+T!!MEfGeS^E0{96z5I4r1ot&Tm|CCS$ZI!s#!noyz@)BN>OcrxiJUw zBS(*V(Ruk5mw7@)7E{&$S*|GCvw(z}hqBG=;LA27ToWtaB+9eDw}0Uao>*|Tf;P^C z{In*=FMi2OJb7xs_bY9PKPXG+l{VpQ@DzQK?lx#YhQ_2U3#PNwBMWO0`A0&_jH_=;@ol|Q79a>0AY9bfRG zY{SM)ei@0s)hI5?mpVtMq$~;|dwm?Xx2=ydc%isA z%_a3NWyNP*&e)T7h^>Vf%{UF7e&v$`G&~uPY|<&Jl)FvmmfrZ5`XbG!K_1mUzAqA7 z^3yZE(#`F;M-Crx9=ms6IBwA-{ky*FjpK)Z^hd_)zWv)B=VeB`=yR(~wozLwDrN=vjhG|sC!aK=%m#FjTz(3Pe$+Bf)Snzu z=1yT?1E*~}e|W48d5sBb&wQ%qOLyKm{@uU(-^a&4@oBdWK8u3=Tp>oGPXvjdu?798 zVj|pQ4r!Q|u?NO6jvYBNuDa?P*5Pe-@Hv5fsi^+vNJMH2tt}d z`@{)}8!g3^7CqrHOzjC;%gg}TeyxOAR6fOzsE24qZB&P7yq%qsM!)v<|H~oI-XrR| zSCcug@2T;%uX_3Tkstk0_aE-q;UorX&am*UjPNl&PmKL?Yp5~`QWjfh+)36ow^O3c z=cI-yqEK@E?0oH}_T~1iI^#BG7EW#l`mNW(h})ofEW~g87LQd@X4|29)$x({W?XjJ zpmZ5+7C~s~wT-V#*N(E$E`-C=dS-|mfVWgd*4K*S z@5lxSJHMRJ;3WT%BZp!3Mmect#z(hfbLyut(4R|^jI}9^=%Y-Y5`2ml9Z@g%!P}grHgBCF(rXP84P=F5U?!XRs12b5nlOmJ*Izpt(D~fEXCL z)x49f?X$>7hqi^Tj16hy6J24(5{{Xzm)M*~Ai5%!bhXZyMms4xo_i+vT=13P_U%-; zgwPzPp)0bg0~wa=Qw5z1(Muzsff5o=V+EG9B{<&|usR<332dThrPt7S1soSZCvt^= z?cvYpDDVM2388y4Wda%(%`N0^+y$T$JqJH0%U8>|H@K=3fO}Uywag*}jFT>8nnX4z zjr8XCz!21F(VZZSATva^J5)pB>5i*GX_Y+(JFbv1`NlWxj~zSC_qR-QHn^A-`j1^`5MA-EUtYNL$Rm%A$G-BIuexC{ zwsAF>+vv7$-|oc)dQ#)sd;m*+Y5QF#LoQQAUv_I_!ERk5^TyB@z3_$d4_BBe8zz)KL)#X*pRFYB&1#Kv3-jSahsOgC z+%L8Af%s@!Ty^8>Vg`I{(B_E({zFCjwHs^M$ixiYPix_!CaVSYMlE>Oj=S%=dwl-( z&%1nAUv-uIye3yTHOZw++}6$F_u6Z(9xr?8OUKuK?JLHMUi_kQ{dL!kOE105d|W+c z(!}lJEMAou<)*Ia*{eFV=L zO?tUnhrQeq$^zKWeJj6Q0TC!GZ0m7@G~1;=pKGG;Q5N^hFequ+4n(RXKU?ctjTeBr zPA5y_>{LDvO4<^wzzo_$?-*Rg2S+OsX@hLsqOpLJA|L#NKN#Nchu}__3`-;;dGfn0SCRvji(*ur9^dPia z`VWhvcfRYLUjTfpO_27mv67-M^>ut#Ta}~BsdA*nu%|2{<3N{}t>xx2m=}^Igmhljo~C&LfGQ)glXo`YE3W3OTeo36 zp~de5_dg(<6BptUKQ%D zuE1A8?8n~N&u`hD!-W0i9~(iMQwkDsKQszcXziZ}256TjPM)cg7c8pyIs{+9IA*D~ z;erb;^n5|1pw*#*aUmzG#3kM2iDurcJ>_LBickL4zLH$dDo^6Q7>tZDr#Bw}y%Y#K z-SmatW{VxjdtY(vYd@N5ykVw+_l}^BE0tH;kQqoe6sy7Q8EBe(Fl#PwBoyjm5;2m< zWV2&}V(NI(1CxHyrV`1{CC{@0WigNBHFmfzwWTka+`9#|3=mn{S+r$IohtUU5P^JQ z_X*(d?9XyS*^+R!e#I5wf$r`R(4V=F5i>aaH~;EiJhup51?L?&azt~XI5M8Xhh14r zU9zkQkgg7*1{vRSdl$F8*~3XQ5Z6Yn=%0lT{P1M!XE@SX1m<0tQ_DM6I8lpu@HL`s z6<~ig)`WsYAQ`G|!aH4OmCE>6s#^(CiOo=2fYj`gc!3L&*Wj^E!;L5!B)`1lPG{LyQsnydf|YFTOwtRi=lGKhO?wkIwEgW zba>!5$aoGCTtU6-uDkq}=nYyFA#%wm8zApM6J47C_hxhy75R$&bb5|NT3^J05)aA>V$C9xsJu zM_(oT@wfiu*sjGrFUaC^Df#XnZO?4R1Kk#svBLDJN^yHAV+F=sC*eq+Nn6>xdE>bA zi(eeS_0HcKn>TR<3X9HYL3m`m_O-7af9rMMK8_waCjOL!mgU*F>lr;dkhqOu0RjFu zR$D`)k;}pje^Lf;bZR3YCfWu~@ZRws-!Z;)*PXtdj|CF^oFV5s#w-Ad^LeT7eEsXk zt6%*spO-7HOI6h9DI^zlIxBsng^9!@isBBMb z!MOacA;SJ1sITHu`DZ<8KYsk=c<7;ry;y(Zi6_Uy4?QIN4*2b<_=GE{*u*X4i~-X` zBC2CD?Xw)yFJV)}fB2l#ykH_gOP_(3=is@Di0#W1oNi`QzGa zt{J!7^1QL@f?eZ+9Xs+2ql(1ys@&?yq}_efencJpwQ#p3<*77ZF>@C9yxR}_k_Q2| zefU4}2)KdkgN;}?nXl9zA$_P;gW z_{Q(@i`n?R+-h+7#Ww*8Z7jL1gz&}>%XIu^9r9h=;DUSe@u{vXn}y^h6v1iWh_y}H zxb1Gu;&>DWSi-~D#&eUr)&7nMdh-Axl0fAv?DpaoU^;R1kYCBVjloNKQ0j~g z91Ca<`Mz`!M_vOLcZ8T{VScUL{Af-9tbI`2sW|H zy|lT~zY3t2Vas`y4FTkG%tR043a;i+FisTml?EP5kaaLShbynVa%|YR-p3q_%eT~} zp~gjkyBf%=Pm0;h@*(-KQ4j44(-;>Oq@_^q8q@9fE?eBXTHEp2P(E*yJvf6_#6~?5#05bv4o0@_j`bYmI{u8sU0Q> z9-v%pu8HCaZUA-tEa-&FCs5P zzD(SNf*d$1f5?rBrw?)*griFg{M|8Gpq;15)td2t{2%}4*t>V1Uob=Z>62%CW$MR% z@+Y(i-J->cv}q<< zj5}Oo(L$KTwc@|?JHIpTfAIdXY4ave9=R==Z!&TPmMb^Nw-`GV98->U&_P> z52CVzTU@!id6+V--#A|Tnpcl+{^oBP+jeZ%1TVLyGC5}=Pn)p6`72-Qj55&&n7A`R z!Z+L&$y>E~v-ejXdu$xozi&MJ=wsvPk)!^$F1J{8BOG# zQGH?e8MhI(DZ>?^o5#`~vqHyC60||1?^WA(O^{?*siVo%wG9#^sZ!ACyownd9g1Xe z4=$qeq8q|zYWF+(mfNqKBmOMNNEb~4OlVoeJovyvi0{wLMmxux>Q-tw05hVOjCICkPxJqKzwK_lcAY3JKu z`_V1jWztr{;f-9==XxNqX+&b*#H+B|aOi*;XRtiH84okg(ca+;FX-Hl^cO$l|EE9o zsqxFd{7Yl^u01M3cn%jp@jf*bcJ#M-Ad9Hta#>CdyqrcjI+NBW0rN=gu32natI|17YYcmSKU2mZ) z7w17eScPOW#z2oevQ%$0P)cD+$oMns=0xLujbn^$PE+|#Yf(&@ufFDLA3y0MxuR;3 zlB9@peK|k3C$hm0La@te;ASZRXJhB2414GfR%dD!cG388~hQEUMl9 zg9pZwk3S*1Ead*ox8<+C`dZgnbemf!`jQ8H zj=AAw{2-DATSM!aAV!$C=Xa!gEF~Locwn4(6YqQo8^RB-wlMz9u!_%^b_{n0r4{WvnVzHwRJNKS@f5JuIGUFWOOD z&q0G1!SI~scxS|0IW_|Ed6~xoA<`8=DWdjGMMr(pX=ex+G zlNy90Z#fc+w;P6`bU>=(LO}@5zmy_A>G74m9%w`tug_jthnt!BCtz0W{@- z7aGl9p=sgvz+g%F**X?Jg>3zmSAz>u_>}7s+Rx9H21GamjnRUYc@#_5wm_OuRX^a8UxivmJ^hW5bHJFoplm z!F6eHE~Q3#(Cd6s7o53g@$;YG_deUUejNvJrVe7&sKRZa*Ij@8_|7+e=Qwsu3ob+r z=u{igB80^$b;p4+1wuEa4R>eTc4gbhKImF-pRgz!OCI4>KMEsMV`owted)_;C z?&OM!WTf)IfrH~4zWJNR>)-GlnpDdkw_)mtgN*X^#EX3Jr_!8P4xBR}L!E<)E?(-F zEYfaM$1!@*rj)i_6P>^M$X|~4zyEh+*9Bt@3o!gZ-jZh|MvUipd5O{w{NNA!ssRJ^ z>8DRA53ZU;Cs!O{rY&{br%sqC@@8zGuu%DUNf8sT|N6VXgz-$hC6|}X@W#~x zS~wp&cGQbxPRP)Qu#?3aZ(wEt#?`j18@ISk?A&$1xcrh!JUQp;{EnSF#`f*oR99m0$a+aq?8I zn8l6;BHHkieJ`LuVybQ_Ak7JmlMJMv646G`ibb2FMRQmV23#)ynV36KOLl)3&6DPu zc$pTUUR*ntExH0QKA&~?@WJsf|K-0N`<~k8uLYb?pW*iVAN$d_j90(r)f%^00E>UJ z14;S4%F_$yxk#1A1j!pRw(w8>&}W?)gBe>wF%-@1%AyfAk9BljA-EkXk+&Z+Uhx?_ z`ZyE%jXVeZs`l|bmc+f#xU{Uyzm%dnicvG&FGB$N}z^k^3zAQw9 zpT}{*4bV2Ypk0oszMzAG3#<=4l63-6bmLD^;Dc3p#dqSdZ0W1INS%sJ@lZ$wqdz?} z9)Ildarnp~^Krc7MBYUgUov*@-lhJL@sxh&qF65aVjyiPu{moP+Zplox%C~G)8dQN zZ-6xD(G^JDk!RD8qwL`LfnybN0T*5M#$7#(#h6BY^7zf}J-f%n7hS3{bNha5SmrfD z6>LR88^9}lg3{F_Crhv8v{{cr(;J`VeeA7vGl7!LX&F;0d3n+urpVCd?Z4uUEPM1i zrcD_BG~V*soP-}{9`F^#HXm~k(lS2?z(?5`XO;q;@5Cq|oo%(x(b07}L)rsbW3vfF zR%irBgEqA-HsO&L6uslCp7RinZq5wfea}6f#OJvf z>^eOzzx;B4R>x<(C6aa_t>_lc)fSsv<>`E}3kbIWn#-Eo>b!aEmPqQx*;^c)ssVZyMXS@9=`g{zkm)J#~Ub+gkB) zMJ@*=O5+L1oN-L?z(p!L;(LI_4p-$iY|5?W8#JjpdHmS;)nEA)zg%YH=1mel&l73# z`TIZfvtA5wCfUx&O%x_ST#Ep2p^ijRtLiv6d&tgpLE&IYcz3?)h+boAb%ko1ii>r-Qfl%Z)s!b!7hl{ zQgzh%kggCOW#%j6a}Ge`#po!)4W+0t`$KW_rjC1z!35H#;{t3D&6@=TygsSmi3GZY zyDMn{D*sUiw>fyl!P#d@S&sQ!+-G?<4^ze z&&E^x_xY+hCl@@1Nhf~eqy_DdDswPeIc zlS3su_@hB78f%|c+1I;`@mR*bef#~E`LrD|i9NRigCZ|E#c#O&dM%(X@-z8(jq%oY z+mFhLOv%d;DWb8v4d5H`qo~T9b`jlOwI-WaxYOxd$k9esUJ{hZ+@JlFY{! z%ZVtv5Cv?rb+BUtOi-XSjcvwTqVsK@rcdz&q<{*cgSRe{YQ9nBNtv4$5O1U9y8yf- zxg|)x>xnjjz34Whp>orYbYkc&s%^-zIvaF_M#*oUZT4*IKPOT_I} zoSvgtgd-q&g+i}!)KL6zV()W{;B#T^&;7zb`^C8e@O^3}^$t#jfI|aW_;8}LcXh1d zE%}1*Rb^3|N(+fSTWEmkOArCJZjeOW2#Goy?Pw*)6L@Rhq5&>mB5A}*gJzO;&B{Pl z4Qc8G?8NIh5#$-n_45Htq?t2%VfEl(TT^z+)3A{!eRbirEDod}I(BHA>esL+N9EIHNbbl%x3~cP3z~h_lK@l9=zNHp(##22 zU~#MS1NT3u#T5&a44&k>cFnqROp8&zTYK@Pm#DnF@i=)p4<_>R{aRKrP&K(>(w+Pg z+7Zr6@u{AgCXhZR7@35JgpTdox7xp)XjrdBG5k!-kIB~U+qR6WuervHVr1Nw&}Sa$ zvL5ncQ+bGEcH7}}K_Tu^_DrRjP-%tvq>3WklDtQgx-Z;uhZj~{fenWe&(cQ2%i`qA z_uW5kzUgLveu(F9ZHs}tWSjV$UxRRTk|$T&l9qP3`@#$TTwQ%9wGVNQ$6-R4XqK&q}v$~p6YdfvB#L16SJcp~r^(onZMvEoCd07WT z+5i(xLaw;@YNQqsXOwnQynOGLMTIx%qOC9ykfO=Eus~N;zr+Ui*Od$;7 z%Ly$&bdpj4>j|NV;-%by%nx^EfO0q$lgx&*bHV7Q0*3H-6+tet3NUo4;SWw~nJHj;FF++1BYK_=Otdg3a-TyFG9zrz<}&w-3iFRq^R6XF==A zc-49U!u0&)y~{4U ztiDa{j6~=71P)Ki$KyMeb6z6ACXc2qXd|$#Mk+|3?efg+MmnovNSe|Wq>QD9yqyN0 zwzZ^%cY>0&2~x@X75c>xu|f<0Z{ z3E)>?8KCT+G^-m4JUM>F(`Z%R`hnR_?6FAr*~MM~It1jO@m^`x zNxI6Vz`CR(CPvQoIv&jcLt^7gSk`5iC-Tg5n!oKp3ADBq8VK~*;LUU!m(6i(sE8n{ zyB-7z=XxO;Fa1rx*a5`4{~o~A_BZ6%RcZqA*>X%GX{s~x#l{@_^6PO0IID6yz2e+e zhuoY+WcWY#cIa~<-w9s0%g)7LR8-N@NZ4?EsA-%6S4O7;9TrrwRZz7(;4gFqmNexp z{lqxfLc)f*-ej4K6MwX64x+(r!+$=P@`QYe5!(j~&qIV~v zT+S>1NoLYpvU8`TjH1DB-ll`Wn}cfr-U)M_jfYOybO^C2xb`g!biFw(ypEN>tfAPE zi(VoO>>!S4q=ot)3iY}Mp)vo`oAyDIdRBK^A) zH;`=g=fHxx;CF;10@sgl$K$VZ9~oJUJwJHc=PtWO6<&mM+vh%)7vji8EWq#tdbrxk z0se*?ZcsUqisJZ<14d;;+pyau#NSy=NN@pmb-%I>hos_bQ*9$SSJglBna|j#8+lVS zj7oUwiO0t+x89n!CCezZWYA?0Re=_Hpf7cREJ5MkfC?oSK3FyeNBgz^_2VuKFKqPVZ(G|mh13ncbyR8SJ97B& zxas;E#!vsu-ybh|=}X6PEu{S{yaZx1y!aq;QKU5g3OY#;|Ez>_N$5V8517b>5YS#4 zh_4iFT{AKEB6!w!%lIn1<4!g|zT@R^obck7{p7(IamM|I=g~KA+Tv$wsfS7DoJ|3Q zZWq;7&_x~!(-gV@Elj8l8Iqj2WSgX@)fqt8TE_wwJml|sH%)PnQbrngKhak1z4tzU z^O-hQnIqsf#Mp86nKQmxeB%u_ru!|f1k#te)5KSh(M|hso|T{Q_@SY2C&8a6h*9L= zx7poK%;0o$P5P>A$SnN~mvyie4^-FJ0>qQLU8g>@*^lZV?(xC?hXbOBD84bH!%3IJ zF5W`i4P%_@5(w^f|-I&kUXtNn{ySRs~CuG5cHla&(^$C*}V_U z$0H#8%Q{`jUHFu~8k(4N<-7uCY*B7SBkZ^-Ce0-fzYplqg6+PD60s#?$(hUa=N7@| z!rFiO^L!#{Ir(?63YsV{R)?J$$HdExvlr%hadI_@|n!}IaN~11`dulYeKVS>vmri znLWA4hx%o}uiwP73g)_$tonvE6uU)~9=|^`wrQeq^7x5y_dR!e!OLWW+i3S|VaeN9 zufFD5O-iV{^0O3h;O6R}7xGivOPT$*{`OgHu)W?Yu)ko|zZQEHwFvck^_5qRhaP@t z?0agjZy85|yqN?#5B+Ed4{HI*TeWYz>1JQC^ZG%X`z-p<>wF?(S>B3B5;(R}ZEOOr zGSP?lB#A%CA{ueNPs&w&2xquLP96wIHz9eDxtE@lN4VR75~g(df{7_*0I&x?a_c!) z^LP>5$3Fhi@#v$E_$ngbjU-?6cwwY^U~I@DUtmA7%?nqhn%_yJa;q=>#0D@)4kH07 z-G@v|;1dZ&>Sxptg+^I?vMPm9s12=(du!Zj$uHD`CNBXM5S8IPaS{;&7R=}^<{}55 zw?Oy^yA6VSZydQZ6kK8VP^$vh-*=sWdP`Zl{Zns#W_q*w&50A^GoQI_y!}7?`uOmN zKkO@-EXruBj00@G8^C=ey11jGV&3OOjP#S2Y;fBlPi@rUiK9F#ermk-TVFeV>aA}b zyLMeTj;gywlm*oQ8@!gE^sNHX@j=?` zx#?87tNpBYs7TjnOC%?G`OPQc_?dw_8qWI4FDG;0n>8=%9eyFo+x_1W6G${3-tt|A z;n8NBDO{r7<-Y)QWK1eY%nVTuQX%Q!Z1_FLYL`(IP6j;k$Rp!nZ5uXd5!>U04xu?Q zqH#bAVDh{1h8xrtH~Eo`S*P~W$C%RXZW`DGm=}{~T1=ws?F&IMMn@9`CL<7>q_Bp^ zduW6;USt!^<5zSdV`yE5oZ#EKZOho9e#E;6I5yDMspq^j6W!4_j}<0PXb=$`FQV-$ zd=+nOU)m99mM+^2rQ7t?egttM$P_Xb96fTxCv3x#I_G$D(Zv^u5Mj3iGqgR5lznMq z-L^Zk+8lL40eI%+^_4*TGUI9Rgxcmt z5s^yACo5^q+x&oNP9iPQz_ZlvGF`ZnwVOC9J^3wRCd4KX_!f*S@`}xAr-G#~2o+CO z`l(N>(9=9CfOt0ZTA!kGcD;)z$(5)1wGoA#jq3M#4MJ^J*=df@ffdn?bRE%5r|i!y zg3pDz5?q6Nbyh=p7hmcy7Uu#E=-A!4O*O3KB|V7=OKYjo>B!S4r%Y-S_?W<8ZpH$Lb+Bx*O(BCI`qyxRUh585z1j>hLVy;* z6c0H6qD`S}NL@sKWZ9&<1~2lWKBJXTShXSUROF04FT=S1%lG@6p|%@Vo|_Wi>653& z&I>LamtA_PuWAIuVH=Vc|GphKrj<=jXuRu*O}L#4rk~oNpO?c&(6tccs^|qfcaGaW zcbg^~xgwpuw?;lcFkbqS7ZdZ97}~PyQ?naFU%5e-?IF!25_jyT-Z|J|35PsV;InUR zqk_6c&Nic88(jt-ZiBmA{A+8?+eSGq!Hs z?6CvC+FHZ_XIcKXt|9`8y6Gw#4q_ggoe+C%mVaWbGyTM}&=s5fX4{p9ByBZ)P06D3 zq9=5^k2^DD$Pjyo#LxJflMV=XVg>JV zhYuff>n&Gz^_R)Kj7qrsZ1IZK+9dCnU8y~8*|c#SJa};Yr53%v{jPV9Kl}5)7>6{u z9ywnD#qm{272apwW0vX8NPfb*kS(D$&55w%M~{weTepm#_=%qw-|_l4 z*niw&ZMTY_PX2PdU+XvLP?)=hS zF7q0`ku4eIvBS3nD+|V)Yc$sF*>iDd^l3J1vQB3|I_-zZZDQ|_)Oa~8% z^1uR`vLakQE}prsNYZr$trEQv&o)I0=KKM0Y?xWx-b@SKApa5J2Si89z*p^L6}W#F zOhrJCBD23*PZ*Z=1&2=lCe1+GcAYkF^T%$ZrW0@4GLM4Bu?N(A6+$LW5c%3F9&jw^ zG_Go^0QsO@XP&7k6pc9L(B|U@IKF|qY4#OiZL*VoNIsBBvyCD>w+KELya?__5U>{& z&}eb?!h_S+P`nPSA)2?LXoi+s@b=~bv>P9k=3RnllZ^#lSwRP{e9|g{TR+c$(MXDJ zUP8&z$C}lkGM7#4(*PN;sx_kisVx`dK#-U;HH zhGgHg%3~5^fg@Y0S4{S-0L7tC<%sRg2icP*^TikTjrpLNASUpXy%$(`(5*&EEIznW zimPRb(sf|eWbk}$h10~-S3tt;{76Th{L}WH4aodl-`QR^ldS-%|HR1&ou2HH7d$P( z9t0X^e>m`lnGtCQs}MNeIfStuX0Yvv!@ob;}j;1KM(BMINMn zWhZY--nf~UobgQKNz1davS#{@c$V!o{TkWuk@?y>$z-xZ7Ggquo8xBb7I8fM$fM)7 z&wg&)amN=_rqlAr4qu_q?X*CyjAIvdMmzIe22#XCcbbq9(3T96QU26s64<1Twq=OT zNp2Y{nCftngP_eCoJOHRm<-0B;S4W$8DnUI-aHff;+MR5yzTG3ZQT0&TgUMeC;j$r zG|-Q+6F>R6J;n#hgI?D+*(You))bF<9#aCVSPiS?CosLY)$ljb@GXGtm|Jn{b0xT3 zTt(;32gXFkNB1dsN)0~8zucaV4#qQ*s+l_%G#T*6Gyx+xe#~1GyXSLw;xABodOog*f`GU7WUwGk# zrm-z)fM_dZ z0pcm+iZ(^wtMVt=qy?n?CZXq_?7fNJ{AMxMJ`8WS%{d-OOnd#Q6I&uB9-_3l2^33q z)Ks@AVw8ux1a52H&nyrH1XA+cBKTZb`}6-S&jh!>;xKv3@xlowhI3&>gPLRk5LaKp zD!wV+Tk}>WuAnI{;)=YiBDR}sNMj6JH6-{KylI>bFcVq;X(EPsp=IHq)8J5ilit>? zT{Yw!+>#du7Y@cmeKwZ~mzX@E6(E{HC_rcM)eS3UOMarvnA2=PSelmsP8gF};^-pD zl4eH>KOovn>y8A?j*GsTS1BYpAAv%0qHG+@d6t)hC-UfG!ExZ=0bdP_f3!f-LWNIA zut@S;KxOpeLXb)3xj=TYpsfhZzN!5bU+Pg@dfR5~4X>kycuOP~nS|!eZr83|zRmUE zLB1E8=e4-1>4S*u=XT0#ueo|`(jv|We#)V`_F`E@i*_bE*p=7{16F~3rI4vaCcd;K z7GCI81RE7H(ciAg{B5`0=DKD}U7hDEp*P)hlNOd+#~BVvR^rPd=du^2UkZb$&Lt>(WLzQNrh_Uh?7> ziQbbaAPWzQO%{~jblXO#Qn^p1jWdU#Eixg$`KBAk{sRa60xSDP8%q}SBg!r0{#@6Y zGt&!?uz$LZk@C4r_*|$0NGtk?fO7KeCs(n!#gQvK_?q&fWB>lW<1?TA%=oOfLux-; zwD98dMSOEMc5Bk_qRqojEolgD;nuVt((cB^H#{o9mvT)cG1C~ zIdj(S_o6*}#t;4A4~;i{|C`+Jc&VPvET~dCFYKkQ_=HEDATonFvJaN>bu5_^F3_1& zyn*<=>C@9_(T+p(@?3^T7j%~?a1JabQ;tr969g^wU`6MfK zDV&fKnJDB=A0G?N7qEU2CjXMy>8kgPyFjNmEbA+I5l=lXc_VMj`MVqqVC0=xWQde* z_#Fpg_ftCYiHFh*?M%HuA(bu4K+w6&@ZvlA4-nKrFpG6bH0DQ0c{-sT`c%PDKk z8~YaqETHty1s62myv0|-SJ(xCi{i{nAvJ~zzfOi`0t-xsB7*vWE0Sja+NkPXN}Fpq=06U+jT4;8jY-2y@yEy8$6(-PiY;n z!+?THn$rkMJ~09D#3p-I>6r#|ND7*5_Ty3;8+BH+Zus3HMDKhE*>d31Ry-s}8d_;o zU^#3p20TD&VAk6})C*wl+boS7#IcQ+Wbiqh!$*$P6-*{gvPFZ>g&af__rw!FGs#vO z`j&abc4JXbQYD+uHZIHSy>SEO70;xz>Nh;0c_JLsD~&KH6Ed!FoIH7AJaFIrUIcpq zEH$({4)Ui?oEW<<+%+z{^fF(KL>8OL(+e>4mHt+5rd2Sf6+pl@=t2+a#^nCEmt0~#1hFT-0xMi@MQVuS4YVz{;UeL4 z<}0|@dP~sdRsw$ER#ZNT^`$S}>08RV3JM!_&NHihC%}fy8^>dhJmyK{wbxy%Nh6<0 zI_<^qbk$n=Yz~v?$wrs9aAM+ABF`GG)1>>7%Pt*HX%Wl|+G3;1AlsOTV&BdSc8;sA zymD;Pf|buY^|w38h&R^q$*#PlEg9N()V+V1hMds^H&=FOr&(k>5njpr3Yp5qr<(4* z^RDsfPk(0Ieh1&se#R3io-N~h$CS+zN$OkKxvZ4Pd4~o-wy%ksHX#C1wNX#dDri^{ zjWZp(|6#v=o$gROS(Gl*la=PMeB_D}S{o`zn-C2$TtwlAzT|~ASK|tZjs{t1HL;bd zr>%2E#tU1~cnNndE=F@c=`D8ANw(1{XLruID-~GIac%tPqzRIGZUX%Qba5HznAgCe9!lR zQ|`V>8<1@hN(??^gN1KAZ?`^IV1r|jb-pk1$>@4iu( zV;@8;CXG5m&bxvIKBWU7osR-1Bm$av0Ni#o9%AawHikz2+MAXz{NMyeO$(iqqx<&l zl^%3knZh;Wl1ne~NlqVD4U`pO8ha=KB9wtJc^EKEk+Rfz#U@ACDM)>or8j~KqgIiQ zcW78f&|95Qkh}os;IV?OEU0+u(=i_a;=5TMz=*Qb{Lv7e=3Q(h+bWVr%L8R&ZEokj zs*>1BfOn=@&K?oPb%)zA&G)2W!o zo8CZtN$WT;(^7fb+_FHIIs_(*W^(ieg+^nDTv3e~M5aUWj7!=mbRje%x4`J~fyTPH z$xETh(Hjv93t8C-f$%_2XLKGDzXG0>Auk3McuaN%AS=+;F%vt)s^IgW4nRvs2rV-C z?xxV9ajmXWVqepRhYx@csD)11?>xFEI;OmkflMGivl3ChEFk!Nz@Y>CRc;MtQpQA( z+Xh*Hut4BUI_z0QlNXy67@uttRK6>~{3P@yfocnh1ESRcox}0D;Jhrxj{p2agcp5% z;r8489a>0C*qDP*pPuNbPOrcIIy8CE@)>ZX?ZEiaanrF8VG{*Kn?P|ztpl5O4q(LFc{@XK#GcOPmcn z>2?EKQEe)D;w15)uSo1oXL3Y2IY~gpaixp5gzh^3{PD#*z67HMSUe)*i6U(RA<5r! z_dR~L+Ap}$WRbSQ@xUhlDnInjIJ*Ygy670Bx?mB#W%K57{dL!mV@HpSC!ToRwql#@ z6aSH;N4>DQ>86`~JNEv4`^S?{KI!`8K;$yx2I#vZMS`XeEj2|7!N-1fPJ=c^M-N$j-9?Lr1>Pplr+Ne z77J}R8SSX|ZpY-nr<3p}Ao# zyzl+v_kRBazUs?ujGSEIF#$gVFIi4d%*TgPSmg}@W$^P>o{4a#cxiE#6R$&yIT$b4VLs5rMTRwi^(YlklL`%PKkd2 zqE#F#?J^`z2>(Qxp>+uyEaFz=4S?46tlW5SB*<9yCiSWFA<*v(4X%-Q(m7W;w|een)G9jPiWKiuY9w`1bmByNG$E1<1P-1 zvdK9J@EMyaHiP}n1}`aW;ECH-+AWmQho#(cz+FyXzW;t58+1&NzdfFEHCNF6^Z4KtyFJ#J zYhNpF-znd8iImyd3GaGC9#YJc3_S7=v@pX4DCm4o2CNZeG)fqZ5rV zLZ=>J=yVWdiG!uBl1>?u4~b}qE+7kLcpVL&_@Sn~Lp#qWZVw(f2*uJYG`4NoI(F~b zqvn)4lXFO^E%GzYwi>LwZ~?3a(U=!HjjeSwtd0wJwCJw5B~8|$PhtGzgax!50XspF zX5J!9G&VQ9Y0JLkSCkzHo_cJ0`bT7&u2|XF^@kt8)8$%+$pz4eqi53MJz#n<_aiqA zP^teYTS<4FF7%uW)hErfC~xIuFi!rYGanFF*AK8jQ*VlDyh0P@W%KvKoiOEK*5LAs z#qf{n*8=1ff4R5~El8l>bBo|}p>Btc!_#o+^5D>l?#c!hH1o!}GhcW^U&)(PplR%v zwY7@Z>7s!eFKFEKr410I(JDiuL4d=ONgIR=b*5RCEqNPgFs3&xHstI~brHqg_?+g5 z!*neFD{pqBfeYHFtzU8b+YK1q#7V9?&=yE6PIHR5lW^ z=E*0X@Q3ry*Mg64x>`u$R-I!}ENhx~$;W7u8r(Lt$zZdGst_%~@B=Sf*}3xqpIG>U zCZDIz@G`Q)<0UV9>G+zLzueC#+7|PtJ&=#fXS$$l1w1!07C!BjMjKTCn-P-|PI?yn z)TI}PKCg!*irKtlQJiND z&91N)=Gf(fF*H{uTjWHFT4Lh$8Ro>ypAQS zLD3Z*qPjw4d!ki;Y{H!~Q{#Q_d#@j}*rGO#KJNZGdiaRH0C3Cm zo;OaNIVExRbrg_a{@V1zUgr%#K5|O62S~!5H@JNR5T`EbPpxC7TZBGoXjw`poVITk z@RY+G%7gkKKjM*h?yyGgs> z_M{mtI}~wI%u@BOeNqD~9?xiu;h4qULGvR{!}Au#WsX&)7zyh|Q#R_FPe8$Gvv1I5eV8!6b7V@~gA3qE!^N*pY_6F5;IK7P>=Uf7cp`&mzdqD^|2 zkhx!Sne&1#`W(@2)?quXi^SmOoCHb_yo#swgf{2j%&`?RTQy}N&F`RKMPvcc$z?Id zTYu*hgYLZRE-#LJYnXKO?X$cbg@w+IH{O_qr}azHf$UKnvpf-xQzs}>tnb+X zyX>b#%*PKwAF8D9s;jRW>o;xkA{d;v()uM#o|s23ZGV}^gqfCDw9#D54RQC54Me*VJeFx0F{?^ojP^e-%-Bm%B%c**HceEu6p8SE!3T+9MZ)V;R`Of zaNKaib>juMzCeri%g2EO2gjpddCU`A+h~c(M_5R?a^tLPd?QtngrL}5c()n)ffskG zANmIic5Jx+{s+hBKL7dgk&pcK`26Q@_X}CL62XwgofDfkZ*-kvv)hsXltH0&#|ED? z(8SHImoK;ig+cUFp4Vdn2TvQBx{_=gU63+S1~%%#PNR&z)LIxAiFzm&3Ii!Ye+aSY^7eTU9ToKJr0Q{$cQ{4M*B{*`thKE?TF zHjgztPmAC)8jk?qIRm1w%{D(}Hz8E>6i)uRg0cil1ugCgoRt0+4hY%8Ntxzym|}at z#i2iAB)*tIyegA@qaTZ0>iY}or^k52L+zB40O-sk9yt!uUO18Wf?J>GlcteJ|6Kk+ z#x!eJxH{EF87!TsS=eE45va^6Q!&h76{49p;PP9BVBrsiN#Z1yN~Q92+0DU~Zt4V{ z$u=PJKn=R$`=Y@Ov~T(PiYlQnKDk?(TEmelzqUu@8dTM@AE zQs0az-09)*L`C4FD0R>f@dz5i7DH_p589mu7`G64X#kS~+ei)DoShHw4?3&j!1umDfMlbQE zD`e*xyukV@bY4YrD8#HR2Ek(kdF59;66#5|Z$XplA`8hIZ%>~(F}{4?y0*JYbIaeV=~IE+NVyO_Pc6*Cf@SmFq3w63-svmt+lE%RK^oC zAmTXk#Kb$7M=8kJo#?_qw{S05u!}bBG(bX|Hf`_%^f%t|8~$D@&;Q~#uFRT0nfWT; zG5PoFzy2G>>t6RdFJf7=QJ(ZyHWtBTPB~Nmo|G7359-jhMw1vm(XmPOb^Q3z@h5-s zC*wK+l zbn}hl#v896S6y+{xZ<+Q{c;xSoLiy!#xhqd@qfF)0S%#OwnrJ0m)n{8rF|+Ue0Ta3 zSE=}<5VsrKK=In(Y$|s@N>ZwV!-CDq3q5SUxfLDSWS)m-hMXQ7upuWFhWilx#_iW* zjrioNLq`seyY9SaeDOS)wS6z99(^%*b`qOR*W4nIj zM!r^OU4U~`*vHTU`lJ0aF&b8yg5ppp-;%e;MJpcf1=N=UCpo#|GVhGq82!TCrX<$7`E8epaNryaX~-G|ZceTw|o$rqT&j?uWtEMMB~zh|Ml~u zJZ00<@{|77H)X2~SOg)*o1hOKIN)(2Cj&VS(Du1=fIDv_D}671@r%c{t=rUw>XvZt zC}YMaApTX}u83!YWqAc{kfW5J%#dBAw{oX-1R${$6gdA9!w1fbc9N6ZTm^-Nx^EaQ&2@kwufU#R%Dzc8QOYkH=5zZyL6Tr+tHTwyIzL+UD`7>$Us_i7|*{ z)TFBc8Nf_Y(a9vRE`@7?Pcd7ggyl-lv>anVH=`6Zd0fc2H&0*^s9 z5M|0o0T^IQ?2t;QVKu~21%)(k!=w{AHsW7}SLK03x~WbpIp+5V>9w!RE3a?qf z8z9WQE}m_LH?;69!1R?g+JcV-3RiJUCrYY437z`Df-`BcaVo9@+6L)Mt!W*3R6_Wa zmNCY{ZATbI$4@JH<2wY{8VBGZov`sh_p89U=>W&dRI}{Uv56+u66D}h%ObGZ3WYxI zDUtqaQT@=tcxS7?Z6ZgdXT~*q&TnI%gM#x8966%8Syo)22NxgE3szR-458!OmAr2B z(ooIHVDc&z&!)F)YISZ)UWYmWGRbn>+)9@)4Z*x>0j64Ev~t@K2iP2BX+#;s;4Q{v zY&s3EGAM`*@O61>^3LQoSHtsN zPbLBf_U#{Awrn0-wr#VT)B$?Z{#fu}KX1}>{?4au;<;9$i32O@AqCJMJEKn(DjGIK zjJ(X-zH#R8#p^DA3{oJPRiiW8*3BEopZ?jO`S#V#n>WdqEb^oOlqNsCJnN0$`G#@L zwbzeh$4^Q|K9MO_36mAZ#s=q^+@0srhR|Khj`O35vKX0pA{Smr^1s_WFO`~VJD`cY zpS^}mHdA}YXE2aZ6ExFlkLZ#Gq*psoG|6z9WD8{*i?Xwx6d1(R?QXr=!}cv3$LBux zx$&O&{O7TD!}>g5EntF`D`G4JpY}wO7plGC^=}xjc*QH+E__QblU=IX1dR)#K!;leQUq zkz;-Hv5$Uq{NW$|!FW>bmjxKlp#n557H<@h38R~va39n03wGdBMf~i${jEO?>NnU3 z4>V88rAX6g>!w}vyfM$zpHkmpL61Crg_p2#i}#H;+%T@b<|==BWykjIvbPR|(!-)H zlUS*jQMON6z(AgEGs@EwKJiX3M(5j`krnRoy6jR$ z3X-qm2GK-t+gtEBRjzmWs_YhY{Se~cv|0Rh;`niI+}8VDZ~RUzYV!7SK6_+PCaypB zWaVF;A?75?MzxdpD0amZ{8YEadfX%KWD>(92(O8b!#B~I1R|o#uY^b@85%%2EQpQd z#a_I;ojoTw;iB)E#i3e+<$Z!lH2lPK@09(I|M*YFAN;`|xDGd{PW;k6m+_f#^4JND zkz2-F-tw05yyriE96NCgarbY)H9(PR76neJbRcasK53h>vnC>@J6(!gYBRD4NSK71 zm-33{i2|F5yl`uc%ITQ)VRted#2G6hPpyhe{<`a~yT{{Ce8ppc+mtr@tlFob>19B$}LYj$hi+cm<^kgWzfii5<2lpP3F; zIu*FNoWowpq?}NJ>mTrKeyS58s>>{swIw;O)zXmS5^_9v2Ck{z*4A>57E=zXvE` zn|-qaQ0n|rM}g*TS%Hla$nW!5%@+G+TWGD?ix9Syt4tOlb2TDv{*as~{?fy7?V5|W zSBB3)!+HA;9hN7Vrr;)fvqE5rKO3y#%?MI)C^P^XRq?pC1Ph+O8JZ8dWnK-TyFpO# zW>F_BRyTrYk)va~8<9k4HO0H43`-hvBz32S6diMiO?lapcVx_@1{%4fWuexK;0BZ> z$S!(4St`4xe7#TTyp#}bpy}+>2>?^c-;Cjnp zFHo#3SDLI}(JXXObKW@36*G1Eo*Y?FTLuCC60nL+UqBl=L0b|X!J&x{@Ike31L+0M zhO)NWo~*zxE08lgdbygp(VyIT@4MgaNl>m}t~6&Q|=kEqLl1EE2)c zkAIZFUkQC%WB6xZBITS!Gp2NYZX1gF7GBlo=8YT1AN|1}jz9VHKObASZ?g=a8sUm6 zkVWv*e!=CBo%#N_gI?O?~&B67s8bb0Un}zUf2U#{A@yPmPBk zdU)*Jw^x(R!@k`Zzw=TzKMO5++6)V>&bud^Y!GP?eK$ZnhYvX!XN!!3rv7`}3m;|7 zq%@Mqu&CqtdQOmBwCAGn`Zv6OeDgPb?lVV*Uvs99_gf? zhXMOQU_dTX!LS3@lSkWY}>ZQ&&87FHY=YUK74Roc)_mm<8S%#apTRms9zmRzW$*+n7E0M zk+D)@EMqkxbw%A(Xi{*;Ob|vHY_#IZM0gd(#2(L8Mvh&^p@Zs&sMcI@M}x|%@mF#j*L(#Njj{tXqM{Vx5Bo}6 z+u__ReFZcfUFfW+=}TD3uhvz(6=08DB^y!)^o962ZKc~n<-63|wi{ORMn{gj5lNkR z?6(?ts|+F}zd&DniaysoMD|1@4@kyx*gn|-tx&^kmwC*ed||VF=rIL7gi9UKopz_F z<{&5tTtoDs3PMBy#d0Q67kT`IAU=z%p=UJczrq0{>3*3=c*-A4+Qx;^MU-OsklT3Ks5ZjNW zy9_}m0LP4_4YG@Tda%wY2F9S%n&E?veiSG$SfaQ>?4;NOuQunS&57g{TBJ#XOd=cc z)UOB8BqkJ{>xv%x(1%HutI59Y3s@T>)T1ICbUcBnG_!JM-g1JnZ>~ehg#^)*5bzyk zK(2YE*X_CE4W)YuVPP@QtnAo2okIt@iY|M30Sa$Gea~&^v+7@q zU>1<#IsLR2pT7Js?7wZBH;=dc*iZPGT|awSbq3Jiu`dS?fLL%afLL(t^S2xeVH+&K zPM+hYoB$^mxVyn8j7-Ui3vP+uyKn#a%fI}q@sW>wWIXZ26MkWu7dzMjzd8g5o7}FR zytpceADpL+P+W6z-~KEaCS_a|U%z34pP-S%zUwW!(T+tb&t-zZ)t_&jHv+q|*2p}SSN z+qOAO5QKEu#Rb)dAb7!4#{8p#+UEEcN{u!a2z^xc?ut)n zkD1i2Q=jAt814K&{QCbj?!W(mv1`{(*AaF8G`IPRk2hssddbD(ZEt(4+T6vy3x=EX z@ol-od~RRDT?97O1C}yHHy8C`-eN)mTdTa`l3rxNqQo{w6Lk$^$u9h!u^ddiY8Os7 zA5z4nN`7)%sWeh)lRWc$-SjyhCkOhO}{! zTsG1dyrhfI65t9gDuH>itGZF0(61RI7-v%3fGiS^YD+kI^sVs4Y@3S}6cZfjzDdYpTzK{pHv>e4TRy8jVPbAQA})B*7#KU=(GI?6SvG_Eb%kY?-3` zL;f+AXXH{*^3(*|`Xh;iNDyEE7{GwQ3?hR-H#+B>znpvS>%P}I=REKGe%+w#nP0u0 z=bXLw+AHm~!`b^pCCm>7V(Lg^lE)|Wh5q$L@Os$rnP9tCp6o{8$kcMuNRkI_cYw9N zO+`(-8$frCxv_2xQzHi!@@6|;4MYIV8eJrPU|tchN;`pQ=v?ywtYlE;HMFxl`No4z z{Ma2nF!QXGZ36rX2ybQ$)I`CURfDh^Ir_PiCqQ?g189P>G-;uhV3}ozag|sF(DMQ* z-QS|j(?Y}BgPqGFl(C8ym7ynBmgBSdX-lCBo@a4*WAFCue4jJ&?7OzJ!uFXL)GKX} zI1`SgEeeZ1d*Lh!dkC9%6+G10%<2>Rv1sF#-aq(*KNx#=?e;+wz)i?LtcmnHzx%t# z+u#1yariJ-F9XSUV3r- z&;RTH;w!#8cI~hkKAAwBh^C6*H_hI9%gy5_fAXibKvvt}3a#)dTWTLW!Ljo}z`P|u z_PJQDCnD6NK>F+lCG1z|giev!G0`eaZh4jrKHl=|ThpXJ6KCmBXpxvhoGXX=`OUKGyri)L*ld%@1C*UpLyEsy7ARx z*~LPU1r)c!@~z!dS_raO#b3v?(50OFwb11%?(t(swdj4(R}6W6?q%Xy98nH0@+q5a z;ALRBgMvn(`qSpI)szA`otpBMWPAh8{(vTZKw`%dbd-pgZe4oJZV#YRcH3QDH31I3^v|SnRaYO&f zMvwy2{0BlLrCjR)Y*Q?OcECgk8&uxSiYVcBC{Srq7PZf%T*fF~__kXM;Jfa=d;Hsf z_wUB@&pqdtv$-FsjnSr096vE$eCg$J(@i&w|KvaUkNuWa4?yQ4gg=ZrmZ`O?t%6I?$5Bbg$`Veh{vR!)VCF7Dy zE_VA`57C#JY8wjBj~#6jd!vLy)?{+%Dxts1=48f! zlSLNcNv_sU z3guDv$OD%w!&0X9+DLCKYpJK{;U{h}olm8@-9}b8X32zxg}gxfA~4A{K$rY1a+iHA zVU82nLtf&)^W53uw6>(3kn?Jd=KG6s}W&&R@kE7GL*psJV$5HWDs+B0nauqJOI3E!ISTu zNEEP5E=ZDODV=6r<*}dJZfy{G!2};$O~$~OPxNkkU4Hx#`m|eQMYi*ZDm(2FTIsj% zm{t;ZrZy2qfq;4lEgKW39D1=;q4;<0+%fLD^Um?hzx*rXtgV~I4lS~#6AIR8@0b@q zf5$t%V|?HP-=_&!uDHi7EOKan#BGhsYDXJV>*Vm~Kawc-9xY zb=Z`Sss|Rg#4toOK6&71WcV>48Jx5but>`RQu63~qG6H9LfBauqnZg~o`F}sWSPz~qX#@!m5HN|whu2juIwV;w@8bUJ0_@G z@GL59gEB0|HrQN+ifG~)UvkAJG-P^_tdK28@D&2!oTjET8Ay4Bk$p#w9(9?ny7J2L zoo|1~c=!9>GcG*;T))hTes7P;Hu}V=)44;z?>V3W(U>F&KfBM^25@;ag8FiM7T)8M zyMwF{-gSc!@VypHa{t4??aMN-qhz6*ohRhrq02@+(>^KZ7ryX?@hiXl%U<+w(u8s_ zreh6dJal0Hxb3#v#!vsF!D)yGMzQF}|RZ4C5b+DqFY$10+P%ZyQq+Kpt! zU*u2}cLNW+=`#R%2Fn18SLXO15{G>IxyyPDi;pnVY1kBkt2U`u((pYvu|DUS#`y)5%8 zwA{cXS37G`951$u-DVg09#t9mj3*+*io`EDXs0#4#fm5`>oi2DM$z&^BXy=Nh0UJ|v(hjM&u2cfcgET1TiL&|& z#Mneg5JC@#rjOppCEh~FLSNGr7~ix(H6SCn_-T&Y5T#{D^Q&y!j$?ljXa`je#^5Ng z23ZMl`2>BCuF^$^a|EU%QaF?sADGxeqH#csS?<9he_~M7+9r8)K~XyyJU+@~o)_Y5 z_N2gz+)enMNt0;QHb^bOb}8h51fOr8RoQ879J-T+!e)3M4j^qX8wYDlA)YqkxYOFa z;8QTsu$=*D!!m%fG4}cj(5Vx?U9K@QIdhd}Hk1z1w&XPM+`#e@pa(AN&D7 zYsyP>&<*hE7;dYCA6sHm^3rCadx1o%lJv1mN=yUJIRewi&)Dt>FMc4;I1_n-!&R9a z{AW*+Z<1(oEPkk@L*&TkR1SZ}g`zd7X~0m+p$R*CyCu|;(-SSOjGVJ)*ZAD${&@Vx zCqLn5Tk$g-Ojsj9AX?f8SA@U+1AlA0>pk!Fl}2#%BkNK?`V=pBqU{MXeyE%%CJHHb z*8z}tybwCO(L_oDRc5I2DWfgp_>rT&H*VYZ?c;l8sfLm!R+jO>< zBs8RD*a^O^tF*mxGb!ym4=Fd6)u#)hCmY@XC(*E`R8hnM!3NOfhLnozz$)DE?6#*&YI z^rPc5pZSc(H%EV_TJr2 zlZ##-?MOGh8+L(@bASj;qaEdeQGDscpb#W4&{t^WfN)bDfi}`4S-e=eacW8O2~!!j z6=cAto$FcgEnBwvQ*C#C>n^vuyp5cbL9#(V_b0(gwHL;QH{Sk6e?Rv02_Fecp7bi8 zyASxR6d7*Qf{f*gxEzfm?WlFMkS;?qm;9uAiw{av$|2hHJ6Z(5afG~*6QPrQw^qo( z$xgoS|CkoRoD^idhK^h3FS}&lxOm^iJ{jr9)HJ3VBqZg_7$5m;@?iPR&YpCo3~+El z!WrZdg}P8gyf|je?>r=sS1I-xg-mYMp(Tf15et{`Pj#cQ7ysnMT>QmmHkhGP$2fIT zvUOa+297hd8T-FDIO*X>IgB&+1RhI}h1`go!A7DAKY&=;fUG7iO>X;*EgXCElWux) zh~sl0c{YO_J4m`JJ<~#?y^^t6WJ(Z=oRlGLEiyw3jvX6iSOXIgJSMhW%T!38@_1Eg z=t3#lVl%x$j-3GY0JQbRow#)6m=Fb_o57MR z=sZGj=se`{sJhgj?EL$S9)?{sA!jyq+=<7eGo_vbZlO9xYPFF0C}t-uMa^?HZoAP zk40R=s|kV*q)fbYXb}=x>EUPldMjD@mSmkx&xU^$R(XJUSwGM)R2gz2p+0ZjSa;(P7Y*Z2ilOh9|UMksdp z>ZOv_zO=zg1%l7!*IL1V)Qp?REmX9T{h}Op%0*3wbVa2%9}V~J}S<5w<`O9MNs@6odlUUnQh{) z3`L-k{Ysvq|0+&tOr>m7EbR1^aYs}hZP1~QZ1hiyRv~ORdC-+!;$25z+KiULWR#8a z04#jDJsqt)mwm^Z-!#7ayWgcn@U?#76$>~{MnohdS@tA3!N(hac`lT;z(O!}CMwgn zO&MG4C+jCgT@s1J)Jm}#pLSkFIU_7-;sg9q{g;y$Ru(*eVyRbI!1z7jh<_}l&7Pa@3%_lY#OBc+zP1+=m1fZf^{?@$Weh&e%Eeg37 zP;5D-&<<^fuoRKZ*mc^EaQTh`I>|Phj6duItO~p%4pbKTLX>tlK1I z($6QIiq?82yTGN~v1uX8Aa3C}&Js^wiA)%#ZX=?On!j{RI@f?TbX$~=i431Q69ik! zLccQvi~2FW@=Kp{Et5R{b-ZK)g!V~U0d3c1DON&pn$&igs#vx23oolouP=hvL%kS_ zqk&zhjn06VacDZw+<7ZM?q1O1*Y+(HO&$WY8C~=QAWZK>h0sb?AEaEn9ik8YnPjAq z$SzddCP=vjEpLJ~M)*E!*Q)veL%KV}w+A(ewk~Xujh06ooHhc-pjFrt6nI>&8XOej z64UxXpoq&XdqkJwKwAxZk!PHFl_Pv^ft6G-5d+|X)3+B!SaiS=gQji>I4pvYYX>c5 zBke5Yk*A&F*g;$Iq?Yn(Z_)0V`YT~s5eTBHHaci#98@_xg@V1xgCx{CUnvW(VWwc`Tev zjAx&D#*3d5v_IuB!KW=!#vlFLKQhj{@Pa(Y%4AjGNfb7eZp<(!-ffb)b6gwo_+K`( z*<8`3-#LZN$Shg@^an(#9VWNDxaL#8_o?yn{{3T{Y<>UtzJFYL`4xVV5sRc~6?m{D z(t6Q}TJd5eVt@I1u0Y zM1tytEKgGHM@XS{%rB7oqtAYNeB>h^8M}6KMQfAaRQ<*`-adZfCw{`u#qnL^v}Zo8 zw8dAB>7S20`p9_bp$Es;zxwrY?|t`Z(skOm5W38?CCO@EMLj!})wWZk1nOt_ixe5| z_t+1G`ULr1C&p!Gw`=DKkjtq}yy;iM+Yb<#%|JBf_!NiN&qY4?tS0T-3DZ?vVFi;s ziUq$=uD@3_gZ6FR`UfCZTk#l5wCV?0%Il_YY0wxLWDnf<1Z&HprJkP zR=fPl*SE+`D z3u5Fc!)8EOWsQyCkVTG&+7>7&CoybKL6b$Cd?zcugaxewNW23tS)!lDI&@3tEIM@V zUyAk>CjcMti89{a&bto4LW9VwuD)vQ-MiOcI-svbvUtlUKK>AEMF4(KuEf2pYOdjQ=jO0_daD@+SP;#}bFN*inwv-<4Xlwu#MYvSSzXAo?_t@~)7aJ;GlU$L$AMh;@dnQ6*ZG&5D1z zc5%6T1yd8NlR6=Fc3U;8q=Z{!Bks9(9Hyw`oFcb*Qnu==0nCZ4CLM zbLE1gW{C@h_=Xr!iB;&fl>$n-Z7hXocmBq_KC=`4iMuHv)Mb%r_xvZ0-6h?8F=D_}nK$_2s?d35wG7{1D* zBAMPK3b9T3BwLF4Ef?ZKLLtBAtTuKa8$Vf)f(&FH1Wc=KX%{Gx$R({jCxa>+y8!s6 z?ealq*}<0hU<}Ba+5+_L8*orfl!C|zKnHKqk&!rMw0+9!D?#gJK?hB+;cOe&V=LGN z&P4VYkqKs-p~c7AleTaeY5DqbyQ*xXYFSX8#e`nDdv@*`-_%6u4}S0W$6kN;SVL*G zMQ*d=MLXa5o!>dW``z!-V(o|rFmqa^^bsxrod`ByM@4;vfiIcUl|zN-%*hb>k@BE{ zG>hbtv1`Zn@t1%3h4HCR{hr?#3~t}0`^E=9_(Nl_CbTDf6{q?!n|5BrBgUFaFS0{m zNSkcH76m3PN+H~=h4U?#bwDzR)>PQ6_RRNtxjOnQAN|$w&AaXzyLRoW3Aowv8^mjmi;wOL7F9z~eFHNd^WmdeK_2c`t+(yaUkRN;OQ7woc z(t`MF1_W|6d&lPXE)^u;k!I8b1kB<)gyz)g`~9? z3BH3zarn>yZ~Md(`^fa9R4|EWgVz#m&Z~plsv}M|M1OF$Kgf`l;LU0yEIyeCxT!1w z9+!uBHeZoNM&}8~odCR@n)eEDcgeoXFCE|U9q$;o+;WTGj?Lsf3tw)h7jF#lpEAr7!>B@qYO8O zU2gz=)_xHk)!}jqCl?hR6GCV-u1Ozvg-Fo&+-E;Ke)E&R>G6(l{aO#|M9T}X_8-_k zZn*B+@qhRS|6p8x*%jm9;X__fQ)jIUhO{wl6a~#{pRRlB?hS9lG~>-~r2(>RSha6+ zq07e%GVx(#QQpWcT>w5v%s3Xb^vz^zr@yZT8=$4nZ1D-LZ+zpMYA45i#oYFZj4OS- zNXgH-OAdDj+;Y>+CO z2KY9OBfKeINT6iLO!?**mv^;ck?lF{P^zK4KXNXrU%T`E*e>M|3R zP6l>#2X)V_6nx0S$ zhPD@i1^pUZ0*kUWNJpP=@#5bVFl9~9HD{b?@H~HN&V9RRosErlHRa1@I{jW>1h0q9 zKlk%L|4%FK#()!XUN#cJrDmMlL<=0S$e*C&;4^>)Gt*kkf-mXhcVle+L=`WZC2b|v z0cdNj>?K(mNhMYQq6J~WY)`;L0gbrQR%4Q)TcIbO^7jTKydK=?01Phh*r=2*(p7dC zrcQz!cY_I>ooE0=fultb$?L)R%199Zd%!ZL1gwM|Un_MP2bwnc9*{|K)sIDhbx0Qn z-JH>a5IP`vF>pc()~10)J2?}r^D4xbLQex;rA@29?a>5?=S?XlpAiW^Z_?e8w}vW> zufi9A;*b_>x7~KD`KML_O+*`9-%e1UGNv_Wec7Cxu6*xWj9zVSw1J>^+Ee=dk@mB*jRQAioLYQcQy$dPf+-S_ym zymPn>QIoRxf8HAK1Gg!9(g$9f4?2V{E2u00eV{H@w|ga7q<-xyUmMRo|C|=J+nvXO znm0kS5a#7UJOg^wl~?!^N;X=4L5!aPKXuaef1ws(x88iqc*on{KCZp)>T&6%m-@DO zzKzS3dY?ck<(P^7eA72=kcmp#kf^9D;uHW~c5S%vH2h3v?F+D!g-oXtCL&NCx&Wh1 zI76pW#q@==#c+hjT4e;$NhhGdljsT3Cexqz)h<^~NV)b) zhW11(x6&kAfC6rRKDhtj_{hKi$oSpg{at?#m}h`9-cYX7a&yz|9FFEtE zSsVR~+v2aj`f5q!P1sok^L`Asbuq`CWs!wNV2%aCDp}pcv<<61Dky&Ez*`K3vF?CE zqAlF{od<+|4uP4L@dZD`2H_Nvl`(3`vjp&K@|;}aGj2Q0MT?d3fUs?B9MJfUaKNk4 z;$QmKlD7JZebYFS&?X-W=bK<|1F6$cG&rk|H8WZnbDuT`d8LE#-6wa2Ec6^&hEx6< zR3A{j;;uCzV`K6F*T3@}D55r8%+(SMzwpoh*?(8j*P);m!D-0$84bM}cATu8 z8-J?F4bv{w=0?zNXA>BgC=tk01;oiqW>1`FSkt?@h6&(tsQ=2~R7h`ultK8?V=?9r zuFwK9v~_+#Vsm;0XoZWc+$!3G=n@bL%=nl9e{kGEMslJAU4HK~+-5g9@eHgiCXnNf zptRjV*)-TR4oD}S(+xg*RyIr^+_DVOU;IKl=6uDHaNZ0cfwg$Sg1$wVLiTRcM1x5z z2VB1A$%4$bxI8V()RvJl(WL>-R)S87yp&d(gW!?Z`m@!5tS!mNbRfu}jjc7PR3-6A z6;I0L8)(tDd(W)sd-r<5!<9l7YXGt!Mu*FkYR`gC zLHeKYh?4$pC$3)zXmjALkFA+=CB1IG%g8Zm(S%G{jIylH}3q#xZ?85#=d>~?1Si(2<<56 z^j2%pU#9kO%PlvLJMOq+-0|i&kBcw9*!uX?5O)xqJbhxE)PfCnz9M^0F|5&<_n3U3wJY7wZ1d!2`acyK~#lamAHa zj33m3mzOks|M!1jyy^Da{fy?(6UTiEy>AD$9PKa(kT93ss78X0%^e2j{6NNlj1@{E z1pinjwD@en1Ci5(BUpnYYFUL}vQIea%P~~?$>)kIy7Y5d2)!4JcIj`>TZp#!6#R~z zJKWFym;dE|9{1mO?>PIMvj?Asfz0Jlf8>)_oIv<{fA44I*YD?U#c}N9am#|nnjGc? z4jQ7<3at$+zXtO`(rGr@aFWimT<_y#vMaMoL;Ros-t8*cLG6XC}OKHs%@6Ic1R zm>xgE!|maGmhbMn?;bC{^pfx3z$UkQWUKiwYA}9t(%`DAt{%7Ea!am=k{J~%04i-E zGA3B5-zpz<=f1U|BhNMztqpEZE@@K+lQ)iWM?vdNNNvo0u{1}nBKV8PIG%py866vV z8#E_wRc^HdSg*e3DjhF&_~aBQu7szLqOAHCsHhD8j_z_eCHA)%jn5d8AlZ2vMIY@YF{8t zM}LDxKc~acbj)vjr^p0oraps%$MWH^-vpB{g{BMw=#7QG=}0bQ8}IRw_EAWH#EK0? zi_A6n2^zmP`%Lr`#QW=E$wygQzG5P$M6qS2v!|R?th*b@0!~W0Xo_2+`0=$*_!lAN ze0>qT9?p8{;9>a&*U7V!TX7->cp3-J4c_%qx7hG&NJDEGff)xK8+@Eit%-waBMZ4} z`2*kpF}Q}Sa*H1fC=4UtDS(JrqJ z6lsj1YF-tqk68Hl%7pyIGm1Q?!?#JFc>MA4 zZ~o1{8HbM^9XodK3O#!C^K*>YqWa(p>ZO-nJbvn@eoBj;bH>pl$LuHTqWo6OGrY&f zw(UDS+2L6l7L81PC?|*Qz8#EsVr8S)sjltv*_XcbrSTiT@d>wC->!X@YFnA1JMC{m zGkJdh-+cdg-}iox>S3Gp#y?1;?kGci1CFcRzWPbFb}wl1dG9^YA||t0L?XzysJX0yx+TzAZjnsXNi#N7ZIU?we3FrlZ@Qq>{w;%e zQ7y(Gqlrgo~B5X+BZL)!yTIu3j|w{?beK zjVmv|V!Z9`Zy7hQQozaQt=toF>~AJB07^Wg&r$E~;BGXCDr{;W^z z9Ml4mmxo!0WT6?8uqS;edIBj!`zATG0m=~`(%G68JU(dLYttqaP9f!-+$tvGuP_cL zDSJ=(C0*S9?J*c0$#g$e-@Ws$yZlyn`a0*Gcn+VtejsDf$G5w=o94K`4f3So*$*WvCANRh`_fF%}0!_)7s3C z2sOdr&vW|l0X(*G;6P3+wm$Yeo^as>=Z!0`zS8w?5h`N85t-*hJ(5;I!b<-Zop4}5 z#SYPt@NTZ(SWeppx4^@1fo9SMbQn5wi*9-j6h=eR*?{0P|5V%xbUe^;lXpB&HjbT~ zAns#yw&ri3O~GG&cXr0JB~R*8nI4;4M%v>%r|z`KNG@!i+QTGsN!vKlL0O*DCxxrX;OVZk#4bu{~GPD97m zd7TbmLl&{oogC8C<_vCeAcVJ6c$`$-rJ@WzaV2Q~pK@ae?KQ984!sW6Jrg_+;`oZK zD-pnr(AxFdz$eT>nh94LSt@i%yHSJKD1QM|9;D7MAZlGji=HSz~hb`j6Mlu33{3+0B63vY*{{%32EMVz*n zmNvUY%OJ(~?Akeg=Tn~=U--fo{aj?9sXnL$7FW%F_(y)!x0HH;NxLFje4G5NTda!E zYJ+G|5Hr&c@u?TIWE6P90lx|1H^U+fAGcfb86n?-sJxw;h}?hwedCw?jZ$7FwN)Zm zxN>!Zi4<)={D%%69#>y=#rW|b{|VK_u3T*uRlE{gPYTCXjwO(T2;{mf_^xc9t&4pu zn0Z0glaD_!KK}8Kk9+RB*SBT!9Z@f|^=DDa+qe1r&J8!+IR4I$erQ~E)s?n~y8uv# zEVn!T`$P!|oPZUx!`bew>KmzM~hckX%PjyJtYay7p5?P|!> zzA~Ot{%#Z421K_IidOuL&}B+_0#;C=wrW?AL^;M3PEsogL z$1|D`v~ynl1FY1uz{jAn!@Q-@TBf=Vl!}Qr?P8T? z3DyPJ0ntl%W*+F#Tm@L6ONmMXJD`>-nd$wk)&zi zYg)zKXuye9laA$!8`jYpry~Wpkfm(phOc)IAB5w4GsQb!Ek&$aQ_3I=rWN{xn3F9Tzk#fwPSZJ z$Y?|2nd||O7uwe2iICFHnf%=J0@GG}vIn4TP_D{fW*MQ$rR}PucGT@8N*O%M$U^1U zKlX87VPUbw3$$1eo|N80hYpR~Zn{NPiygTOq1T9{K=mj*Is`^ z-nK0Mv~?B`r#)G+sL~sIj4(h~kwR;izflG!bTD-Yz9v(owR0O_f?5+!4!eA}^_$=L z#`x8be$1br;tV|kC?+p1!H+C(P`_V`!<%lrVf@U`{ESF8dEsf*b_3-pTb#xK(0B$! zyGjM zzxlo6-S2+aID79o(^cV8C1|_C=h~NT#8?!wz-0o;0tFAV@MW_0)YDJ<#XZkG{mgjr zr5F87@k^S>`zoF2xT52?|FS?vE{kpSpb-_wqrl{qF}X!tKhc@S42r-D-t@sE&uMMQ z@rjAf_ojSJvgwjahDSoP7)`rk63#8!EOxoVi|xC#Fr$w5o_+SX@~X?nwbxuXF1>W$ zxbFJvwP@RJe;^Mzyonc`ES~#k<-*Y((1|wp6QL6+VOs>0 z%`ft^+=#On0e*hqzI(^N`j`JoRm>I7^e3(gvk3SpjR$Xg``gCR<9xy{zQ)|y&&ZV` z3zSaBxuvviv!?~65jHvyQQ}4w72+Us2L5-Z^YQs~)yYuA-Eci7wLEN4OnIq89pfEB z0AEI1>s6ZP`+3g)>tFx6#c^9ceLc_qB8GCI?v-);_))(E@Afxp0j#v&;%YergtEgX zAwOW1DA$JGsU8}iRD}RIwv=fCD%51O88d?{eELL7a~mbg`mnKO6}|fEu@fhK<&&46 zvDn9A#*4=udqVzrKDR;RD{b7N#aq?Szu3j*X@0KJmnpK4DFo@}8{)@V*Inejt>0ysS-vYTW%FOyfAA$&_+6BJ)H)j*5%-~wL|o(vE=#h^{T6A>dI z$yW1?TZq(LhSk{HzD{`k=1|c#v+W3W70&XGZ zAP&SF?UfHd@_y%&zcn6x;!!Q&cTqwgM9+ zTBq$R^gvm*CG8m8`Z2skh9`mm#6DsboZQA2;#YNmZ+mabOxooo2 zLcn!hY2ri~kfD%UeRpZH{`t>;e*D(&{*JE(=eFQnnKiv8FUSIS_|T#8wl}|J{P2(b z@Hinn-*=5MlSPs%d#w}oc&9-8q^UC&1zon>dd&-9w)g-oH)?UaRTJpVhsP$$BST2fFOs(1`9lHz04vy5L;q%QrMtYAs0Jrcziqer|@_JYWp+Y zIi^J_Wuc$YUry`i&x8o)J0etIKmRIX-~Na&%B3H-kALJBe{uZbr$3{9rAd-xz2z-$ z9)Iue|GjbXCHwsREN_2yovS?~BYj3cU+I(IFbcfeifp8wi7P*ob0|z@z|XEH;z2m> z_G6f7E!Z2dl+(22N+&icYd%gA7XrNElzEbZ2qkz7;rZuY@Ga2XYL73Fk1u=i11U0( z$PX7?bdj$BQxCLBJng~2H0&9F;X~6#^}7KM(vq zoX{@jR{~H*gVT?bZS=>NHI6*;@S|vP9~HOz9Cv12ea$uT$)f++zw!;^EDK(-NG^&w zNlDqr53S>BhcR985@Wke3v+ORlsB~411o;l8ZDPaY!Hbq~K1XQf}$w^C+&M;S`4 z+LZN%%JE7VCU1a-USJywj8f8f7gat0$qKI{;p@6`(l({<&ooLvQh5#GE}j3of(_Az z#Y><*TU)fpKk+A{x@}e*s+bxaU6`Rg8H_;GL)wSuO~@mUGE(=Ph$d5McVF-l^7@tF z^{}`d+TOK;9k#1n6Et)u*a=89K{rh{#o>1rmA7nkP1Epdv<%*gD@_HbBST9*TgzF* z;e~E(yrFQQnNUp~ZzEdCjLu9pCfmy13@~Byq(gtj*cFJr_Dj*dkoBa3h+Ht)VVL=R z1yXvP?bdH%$!Oa$WD&Jn3I}x35P^v*PB}Qxk(kQ04!}W-@D@}6edDP5_5FH=C9MGl z(p>2}YdrtLi{r7!A0K}9s(iD3`}T496<7Ew7!&7}IxnX=HOa*Qt=IB+n}*L~n`eZX(1 zr38p_NkoGz7i|H#jTCitpi;gM3@(Z@tiuPO)6n$6Fk9*(SBE%=ZPUV*N%2QM^3n15 zQ;&@uyJY8Jg8YhKfb*XBylcGgz2BS3uW(#hqI_N-89D+M1(mKo0)F*m#41efHYri( zN&{CO5TMp5y!_=oBwV4`Ja(x){Lvr%$@ui=KI;<^ECy4qx&o=c7c(j&pEtSf)|7M?K^g5AzZLftv^~4Z=kMOFmlz`b}D^Za$%!ocAb&6Rg2)AvTMKU^%KAK+v6)= z{IXxx#BHWrfyFLlFo`&H_<*mtzw!3l{k-svH{PrRlosh;z_94VbBuRrk^+^(x1GfV zh1xlyZ1A=wzNDSulbjR~8NAkcM2p}9jyUD!goX>*`3kCOz}gFj3tAk=@`)@}A5x0RlM-udk%hvyU_R5{{s4^gi_I zE84;09XtwTZ`Y9*=lr@X6X4UxDJJhJx8>L=;mPqJxu$iTDCs4j6I$ZXpf~a5WVWPK zS~VaXK1z>_%^VWsF4JsvAA*Z3aF9p`W2bEtzVa0Dh6a3(ysv%btK(bud}~~BZDJ&cMgDY`K@>7H=gvyypPpm*tb6l2F-LZ>| z*>_-I_JUR_@f3IY@cjIP4?N_t4<7*BVXq4+W0>2Tt- z`uPqa!%Lp07uF4Z^c!qfC|ByV$V$Q)f$?|p$2y=y_&z?$@g|hr*O&1VCr*vWH8xV; zfSQTh#$}i8%Sn;RAa;?PjkFagh|ECcW1tNnz-y9kHfV{IjqE3U0Vj^Qx({F3nSR)O zOX%_jCS8)u$xDv`wv$|F@kivL(z>;sr8bcK0^v;Eq8aOLED7~*brPY8dhaRdP_@uBWOFITxoOv!GL4p&uk0d8B)L5+KHV8 znlI3GLHmPdZmYx-Hjre@cLXMU=Kf4wL@(prWTVKK*KncXW5=ff@{(Ag1*K?k(V)WJFM_betBCi-}Ouf*5<(zfTH6q7u?)Nv#p2N1@BsZVuiD==FgQtt`sq;ubMHQ zzsH_bg(rN-`jvnG%f3Bz+YS~|oASa5J~+R(ge#q|(#c zLgRy%5$Q9XYaa2kfG|xR)bJyI<Vy8{{Kl9T+ zH7>Z|BH7CuV38hO**Y$K`3QevZQ3k|!Yi=dlu?kP;iE>SeKQI5BG^C~!BZaTf>uA? z&dk+GzH|J=FMd&zbgn!wnbqVBdX<|inXXI4`JU;mx86Gb&foda*s6sVFZn@Pu24y- z&s>)s-l1B&!cEOg;I;y(aj{J#UU(8h&!lOG7Jc{KcmMdckN?_u@S%s?R<`fhE}GV( zT2Ni=Ke*o~c)sgz{EhLRcfWgFvhPwKuzb6zPo$xPPtx%1N?wAsEja2?ecuaS7ND}n zZDcZCcJ=Hq7@r{E>a|~<6*DA*XGc$s6UR>Yws#gYv_n1z!>!u9U7H0cx9_`sN;g*% zeWer`+F>h;)*ah;_IPu{rqL!7O+}oImuRJJFpA}NpQ>A%iwj*xg_qlnwD=zAe!F<>Ba zey+6BX1D_-CsHFGN&>dCAMo}+>N|083oxfam*^WNh9T`B%v+CQFA==n4XlV!f90>d z`Q*6g-h18teAkEa+^1y&Z5SR9^v-nrvVZ@S%miRZ`Nr$x`Vrg?UsuLaDy&d_d@ zoN0iv-gtPBk#fMlLPi{!MD$NSac%f(0rr!5Vh0S9@07$t$Z?-wQyo$MM;>`(9NK@# zXFKhC(bA7Dzv8lS;rSP+J@9x+WLO#@3rFlGeTx2Hwn%SOM=$zvH;JHjCk*YPs}L$fv9%&vGG-3 zsv86S)5J&zBtwy=b)b#BiBCL}9poo!u+B<^Td=@2Of;pVA^eVMTjiP4&9h7|=?R;r z!$9;3XY%rwcEqR;LSAsybj?lLcWT8rWzjDcuZ{+q!v%4Uv#&3L*Tb|3j+@Jo0y-nf z`Je=@8^TOy?@r;GPFT(l{h2y^I?Re(5<>QYZNdv;!>nr~uztyyxz<3*2iQZG6mbrS z;*CK9*=ZtCU?*e)VPm$c&cBW2-vP4LA<8G2CHmMAjGO2a3I5Swr&GM5LDhWI1{ zz-(s#9I%2H&b00wGeEkreE2I-VEc?;lQ99ZyUyFLSsyqi)EtCgdhsR2x5!nY^2xVEs=WI#3b5S_Q`=)^Cg9<6Ks?pckS3Y z{_1OAAHV;Hf8bj>S<-iTm^i-l(#zw!zU#ZjJKy=vTzx~N#JPUm-Xh%^oFJw^QPUC^ z&TT>R+$79R-{s08&sLt6@AABFej<~9`l<{Ef8M_QhoAoR_<|OcJ7hCCgM(T*1#yj>PBJ8cGul!-LE-n5qtvSVX#9ju33k>F)WOvC}o?6NyWA5<|JKx98} zQ05liPyFU5#@D|7wXwafMD;@W#7X>_gC@1ht7V}D_~a))>6c^e*}YeGZxtQS z>P823bo9uPv2FX-@$UD$XT1OYe{-C@ckeiMlv|`}P)xp=#GkH-Wh^{(f<-W&yV`6y z9v3Mnc2eT57wx@3QjC*I_>SQxZJh;@@S8TfUuoxg16tTzo&}Iz;^H$xPxA~&#YarB z&_!3I9+@Q57O^FE!l#JR-9F5R&y~gw=)hU18IqS0LLWh%wCWd{978M}y~tO&SO`*N z`0N@}ND>M}9&UUi**u>tTeogmdZJ2+E*s^jv#cAO^@10TO$#01A_y9jR=Kv_B{%jX zlC-vvET9waoVqsK*q8eOHN;jri=F)W;Gi z0lhqsmO&_tWhud~`h#UDimiMe?(xSS(*pROq-AgW9Q)c9`r)zTN5{n%U91K0o7_hH zNQ`7=;=gGeIdW`l-^O$I=x7^}gL-f{79h?BL|5pcEqe`ZN1qUk-3Ek`r?f>YtYCuZ z?RfhX8AM53;DdCeA7}n3Bo%JuDF1yTkuB07j44LE+f~fin$R^VeXUCSdWQ;SqEkyUKeQe9N0Ii)SoDi;X zD9B8F*4MOa`2&oT^kMUnxx9i)I14I}EUTby70}+*9;q@&(*U)Z&x8sYe`k3PlM{=p zJ#?AP>ItSI%Ih~k1Kl66ZG%mDlQRS>cJ)?3-iEX@Ol`!piLL_m zx?JCe%K5^YcPoKQfsBvADhXl1s*2ciuU8Gq+!a zq96U?>8GFe^O#p(eYLLubUBe9Ko@|G*jzTDhx!8`!Imanf!N^!YTm?4mHhk>13FpA z^A=wKl#AP%Dc4OmUhj$9GfzM1m-%oK#aEKW!!5MP#~<6bZXYka@X~nb!3W1pH{CeS zIp=IG5OQ$GX39I4O{$d0=Z1nKJzXhMz5;QizD-71MT2e7@%CpHmp4n-t+(CkPc=RK z@WbQSu_JB=)}xJu?Y12|JgL6--h0QL-@McH&Iuo88}5@z^SnI%#Z?%<=WDRV#-JMK zAkw>(#fE_gTT$Z+hn=U@7JAX=O+Ldf$5q!Sh|A9>Pij*hSAj|UZOtc-Cr>t>DjFus z&~OEr_(?6)`EKtiZ;|hXseV}u+iFa)O}re7=cbt#a7C@_opk^tNsEIbdhzboY#jAq z*WeQEXl~RW{>@~){D`Uo_YZT$G4`G9z$Z+CnaCqQc;c(TnClWmF<=MRW_ybVe8&Zj z%5Lj)7PP^~R<_VaHZlnyR+^*d1RT^2nX&q+VTF02OoThqN$A~-}O~S&{hFH zBX|A<=Z)Ln@J5d*2#>Ya3jL6s2(!lv!Elyqp>31>TsE*VM* zN76KbNoTbk{6=VZ39VkIecDdk6u-;!u0u}RJ@MER2=E38z+(zmU3HcGriHN=IYPQm zg|CDwA8Yi(!L$|d#;7J-1nh}aHMu~D7NE2ZhHo|7A`%U(WfjmGTs|`#|Q2BLMCBCw)YH07zXO9=4bOy}qXvz*9yb(pD_uv%Ul zndlmT%qEta@HKt&RA{>$adH;Bp0>-~ar#>797M8CX#$B0$tTB);3l9Fb>L(SjGM^; z4_##Wn4$0&{`r6Z`gelYz~-O(`G4|HaTX5Z%ul(mcI{3&kP*SFf_)Ip=&CK9BqSUt z8EQpCjSx~1P1|A|YUgmqd*Zo{mTCkaLQhb@no_}flW-3wt5l7mxN*h8JT z-Jcvo_z7qJa5SWx#zX52XhYSsCTXa)U~pz+hu1p+IQ$ZD87RN_c;V6E!-w)rlG4y{ z%Or1)KKq<=?W1yel`B#$O^B4GB?I!Y?SZ1oVZ6BwPTN2-i$KmYUXU<*4<4OSGE$d? zcOC}@UQn}36Z_+uY&|eGZOyZxu|JDsU!^(coN@V;S9tObAGa+tHNlPyRKg19c0xI< zD-N)!?2yZ^^?MSM+d$nF6^AVKPgL(LA2a zorPm=hwZi$`y48LLW>ye_aX*_vk4)V|49>Nn*w;lAHA|k<>|444EL+br{AB{Vv8#@ zO!}|A`kL|BV~_dyR&K*(affjkH;^H3D$b;aPYT_C-@W6ai!K}&T&M|7EzFP#Eis!4 z#_0Hst6k{iN^>euQsvrA0>ejnVYNo-$37N==bg(fly4f>Uw@rnTJ_YEPfJ#A`(|Q^ z|G9F<+i7VJU;XM=wUF65Zn)tFw~34?=_{N(aoCCou%Up74(-4T2h}?^;4cb=*^na1 zJ`zwaZnw6tIgy4w+7fa^L%V~PI&~aXDa|d7wmz$%Vk;?yRx58@jdj=gJ}z7))?7+4P|@>_?Y~;?~+T#Ti*N@_fc*O z#-3_y-q^bx0}Am`_k}XrQTxg`CyQ1gBtdvf+}Q%z-tDzBOs|CX6iz_YC(EfL=i{>? zfSIx>C~3+ooPhTJ)KgFSvrt*gN`|sHDaviod-m>8U+2Yw;z^^M%8Zv269~u2zqD7A zDW1A0aslzG6X!&ROF+PgH`!0{vG_kRo`3!Y z6H={igUY|~!V7&D6&Grd5gqLCpmdpxa?Is-Y0zJY)H&rPg_LBa&l4i2YNW=FSRJo& z@@ST>nA(EvLvEuTXFLsmve_Y5>B5`eOoT|CX*(W7^L6=zlmEzu*CUe?)y`}eF=QHT zAZ{G;d#fCWhzX)>FP=sUI_|LX6HdE@jE1J2+WrJ7mp8SOFk(yaU6-L*3mPAh=Pc+I zC+WTkpW+i++WQ4Vo5B+lq=E{Dj_h-H8r z5zdZ8>-mL${?A@t1g`-tf`9&>PENvO_NhHLLnqxZL~HMoCT<223F$y;E2*3%kk^f| zU@eJ({FWDR1F^0`7^w7a=%IFFYiL`WX|lcOVDKhOJ1sB^WpE=_o;Is-es==w2}3#+ zVuW|v6x!p25;_6+=(lRp6-TdSO)Q~ZAOzsp%waieb+iwBfLxK$@wGAKIeW%Vu!3LE zE+lk*^rm}GV16?QRJN5tC$e~ZDYwNQ(4?&=tjIig`0zM;@7Y?UZS&+lO(%;DRCWDC zWXoI|3Y^bw3FOZ-6T1hkC78K30X|*mN}08ZFB7Vv#p5~SJ}taB*ltnT{L-T0gPz6P zO*h}9MbHkF`;-=Dyv3E<(bCosM>}8w27T1EPGHvM10FtrPHEVuZUUZgIw)ojEqeD| zvd`a0eCC;F{CpdWG!`aDj~(}CBW}D28{>N$flBJ3WPm`w7b!}vRIQ;B1dgr}RIAsf za3U?A&L{(RF$v=;=B}N)v|zm6S9Z86%x#YF;5(OJTVEaKDlDIU;VrQH_U-dxIM4l& zEe)lf!#lu1js+fNViF9R9GeDBkMDf@+ueq_!v6dVvQ=%C zNuyP3<1Mw^dbfSs_HoA@cjWd$385FHMnhNAN~fnh7Z%Js(t4t5w04R@mjf|!=sUEx zyl^aZ(DdYn{P1lEi?KFk4R_KG47Rivs?|=h!ISM0VVw>`A4`A;a($Y=D7w8@zEex3 z&F`|(UP&zT1Mtt-@}!JvJG{F$lke6nkkPr$tU zz3+{^r)fcwqo~JNN9|$jN4giVV6BtfE~}E-b=&Gin#mfJw@e0*%06KjkeQ?b9J~sR zE@P5f5?ZzVLVod-#@HbanT2hT04(&7aqm6%jYl7SM83oKY3n|AK!hmakikh<-VFR^ z^+U={Kb{v9z#7|~#&*RzV@XhDn>K8$JwG9#5{OR!Ijs^Lszb}5~| zfwq!%B$$~5O##3_I{CKJ!j?1w^RK}b#P7*F?NJiIu9O(rA&G4K!FQo~`D5G6$-eDd zw~UJ}zR2_`wwX$P&uK_k)QsAUDEp$YlAS09C0#Uko#ts8fkg$+SV=4;2>(QGv@}DE+lJq5jF^*&9q|Gu+V7l}x9YIMuE+FtYMnoHjK&_hj#de4SuP=hvL-m06QaSZZ zkXl@T=qDEPl;8>j0hkqfkZbujf=S>6Q{}DzooU9+x`YF-v~g?L=)_Atz?>8RLatCo z*C3ODhYnWx3b?}OW3vdsCWp?aL79o4(*?z5s0<(2;jgV>8svZpPh=*-PUx29SzETi zf)5@AQ*jsa+NexA8xKyK&Ddf9IUD^evq3~6I6SR*CJr%9ROysnMiUL-?KqyXmp<}YZZM%EU zK6||J_BW1`S_ES;2U%!X$nDT1^`#eI9AEz8m&WF;n}^@*tBEagTyKaM56>zQ+GT)s zMo)5xDo)#hw)v;c1P<2XSpw2#S&Z>~a-M-o9up)MnJj|8{KYSf9otwOGZ|ARn{>AS zvlEa;w(V<3I+MsGO)@b7Ydl*TBPpV&|?szP=bd-@O{TP^_6y=YPG~c(LbqWjQ+mVFHh7k>$fGat zf+=iy-+SLP{?UK+562Jv;17}GyB^5zgBZ6NZ`Z=57Z)rLIbhNkkQlMC4~?X|4X7HG zV1Y?cZNOAO{6Xk4D35Y;wZjKoi-=D0%(G%wCevAdq7R?4GWrT*R$rO4Gp3J zt&M;&j~A2WPK3_V-emgGC(qjKagYU^Zz0Ezq64>U*G?^V4~;+k^dFA@;eYtQjbHk= z|86|-=o90dv-kSW4#t;OcI5C;^^L2<*KgP_ebVg>*$#!Q%v|kS{s%SkbA4d$fa+u!y!kAeNhU^7998Abpg;m!ikn2JC%(*??WL&{cSC+IQ*MJy)Q zkII>^(pOzsNCc-I)_gpZE{(ke)4G%vPh6$9E7iR#6gLJn~aXPja%50>^W^-%O^}UNp^tzt9?@JTP~0s z+pB13fF+(dGP12g`oT;W+ytus#yjk71MqQoZQhig^9XxefyP(Tb}izRVOfvRuL9{B z&t^vblL(u3j)3cJEtGs%bTm$r7!K--VG@_Ka z38sqMNEfxQs1I)7monGV!cW@!g0vop95<=y6wv{dk4?j0{X;<6(&?6#x~bU~Ss;7U zK*?7q`X%k8g9A2X1vUX(!LpH?M-9`G6z}IY!L%mFY^d~W>rUN}gK(9nDk#1wsQ8S6 zADPIS58%NiW;xW^#DiSYSc5K--WeAtxdo9;KJr9$iGjMWgE!z(x_(V*y4-RGP4P6Z z@x)VW42Vv>a>}<>J^0Z5Nx#|Xm^iwk0(+gS%zv0$f-S(K!xt(ufAV+uVmFI1^ z-51@HMZ)`eaLjRBxS$O#r+(CxS4Q9}ZvyBQaAoR(^UwFhkhdCd+rE8h9&F$W>f>4n zUv%+>zIqC+rJ@_1_)P&2cO>DfeL)CT6}SI8-wP?HRZfoY;%#tyx6IJzcDusK27I<> z_wI4s_1BDtA9={%$mL~fev7w??OV*t7T#pZ?VFrzx#ymH>{Av9Naq$vXN?P4F@ zOe6~}ppKynjYHeRKFBO&m6^ZaE{Jk1Z^*-B z2wWe^wXaJvIP5S#zM!H=SPGaqRxHGmR-W|)6F@dNYu2{7GD@<;1=zj`IzL3jm*Z+H ziv5+)G{9Mfvj-Hf(mQVz$S2Q^nRvS`z;90U(q<kll}5b z``r)z&fodbap|R(`lO>RhLAwNFs&(j#}TEtMxhy{NXN^ANk}igDHcQg99Wx&a35nD zu)F9TC@*hH7v5y#OP^4YgFME}#Q8VaDhc5QVVpeu+SmSSyzu;U9?MXfb^=dIP#iv~ zcA5Ni#~ruZHtv!!*fz+a#Tx($yB%P`!hnJ*&LR?+Q;E&lu^apv7Tb`#vb`YG3lL3k z+D}5TP+O0ylEt{m2~NKMo)dw>E1PzA)zw$|&J@PZ=!?8^!@>gUBgeV`1T#JAEw`cS zJ7yu9$|KRVEs3&13qJX)v@_juYZ)BJo2_kTJZ?5*Kl{wH{*0boVm!~)Z}B@aA`iOg z;?WU!XT8K{nuKhN_6$sUgvDEYp4-^$GLQuP?V~D>ub%@(j~PNb(UGU1(v)Eu+e;`iSI6ub z?{wusKj8{Gy%vvBVT7xsAo(c|(WdXXPeL1oKH5p@z~DHUz0q!$(0E`;$F@A)*ctgb z-8g{w0%*h7t0=VL%r2tjONG$PeJ0=}JDHtFq99DUEu`p?`TCXM^>EgU2M%|w2$q%I z9$ec1(t)xOD4ZJ2YtR~AP3{6W$#tT_hR`C#pvZDCT?NwQby#5eZY~ZPI6B{raM2mz z^}s@$NoG)jwPm2;$u`l_Sc8g=SzbdL={z71@5Z0bn*jvwwr42=xymD3uul8}(z%Mz z&}C(t%N_a4I&1$oENKD7@taW_&{8M-A+vpyL%x9?J`KoRLFJa{6DN+12OhXT&v$83 z4?kz*S+JaY{<-7i@qF{u3o*&zMLZn%cuQyWTPTr&wx?}2k!+zZmvl3-!|U)?sxf3 zqu7%JSFUt$EA&#WKO8k;27$I7Wt1xhpN<_Z%&{^fuF z%j3o8pC8+H?l2GeM~)sEd-v`gfA{bHtluKd^I~a}2vCR_+MU!Sn{x36=WeUnu;o<% zISZ34*fJHk4IquD`m5|eDS&G$HzYY@$nQd^*Vb`c*W=2l11tAlsWkI z=&=*y=9_OGKls5P7&}y608K%%zOD|?7IU)845H^s3T+TbA5@9+HcNbfycimi1-K4r z+ae+xk65^Wr_)#b3&oOeTOtXrLTuo~5wUEsF+^;s?=wTmTmh8P4!|#Y*UEi$X!~va zWN)}vU>!2P#jmPK#YMmb7^u3ztW46=7wso4e3{VtrFud<{q(crGoShN_~IA8G!7m- z;P%dU$T7_Igjj{R|JaeE{u~&$^nU2aKRn)e#~a6~6SNN&!3$7=K7wV8zgBF5_$F19 zcJ6W)K$5(Qm`|IL-!7Or0Wh&rM`&A*|)5Os#WSuEw1i$SvYUUB4<=Xwx<<;}AqMcF>1X zZ%xzscoX{Oaa4=n#~*uwR!}b1PVMNj%P!S%V|QKsCqwe2mlKp*w`_I0icjpw65kOv zY=jRS+eQ$ZGWT%Q;C|Q$+3uDhf18@|rhFd?#%RT;he=-W5rGYL0%rnbK_naDo0LO~ z-33bews+;5qV!C#HoXAYYG^bx)r4BZyX+e?kd~#8DcZRk)1C=WnE>z`<#C);&Xk3+ zQaEeOwqo-c>emH_X4yu`-+*?~1vGu9XPDZsSTlzZmBwhyVK!qwOD}EMBe>$!SgI~{ z4c}}&yzv!UxtMV6g|ELIdM%vw;{HSKQ!5RG3a}U1Kz69DCKqXlpk~^1@}?zFeCi>J zL)*$$*H9wQcOeTG$1v)07f|`r^;OR!{ z=9fJ1v1yh=ocv^k4!rFZOeo4g@tReTD^eV;+NT92x*>9rxe%buVyt)$XIcdl68W88 zhQgb?(v$4QMOH#+75ASqSLdJF12ly*UNl0-9&9DVE^Uf(#gyk$pXOO5Oq^T*Jy8zoLBrnv+#NEhA3$fIb z;@UwDPq(Mdnv5Mga%B9*ul<@9lSlm-pp%;D!vP()pHYmz{bPT7oPXiPrm|zO_feftV`(M1|yy9DNpM2tp@$rxSs-H>q1W9$s zBclvB;Lv#EZMTje{*fQ{T?i*mX@PGS=GkoKJya|{aQjTnWhheGb?%9H*(xAb*$K7d zu7VUxJJHitY1_UP9=SrF6ajZUP)4LsCco)gX(r}e(MCIyG4ekD7k@tPx##Y2-Ssz& zx4+{%v?$u?7jm)XC2MU!*<}3!^rZl{(K`yFdLl|GfzYF?gh*HxxrryNcqJ{0J_Xu< z181-=Adcb$#*hJXErOjVHqjfB078IUe zqT$N~MA^2BHm*eRJ7A~s_&C_QYyjyQMY(A6Ge_(v>bARN;@8Kf{ z$DTcB`-GJrO%OeI47fc=Id>EsI&^Sce%Te{eeZkU_|EV88)L_=UE}!iW8<{OlIYU5 zC?{p|BuhHMV3WrT?4ivmh&Tlo=GsvD&wg$T0c|$AX6*czE1<-#rq~!Y5aN={@v0RPv^0 zlw&H3o-3}na@?kIfLmf2U*PlAc+{b$%I3lgF_o8q_D_rl_6sx?r(HGa zHQ-GB#ntpiSGxyVkD&8_$c7GH%7-t>Lxw`o^21|~KJIrU_;{i=%CUyA^7`wp9b2|; zHy_}=_^l0lgbxlu(qcL`@~TgiFD6<8<%m6rV`u6vs>qWYX>-j)TR@Mshc6)wk~qDu zp(p&g(}zCCSjzFXk0TV78hzsNC&r<}JPT~CqSf4D>$Y+A)mI|G*vMB5->H6mXO9gl zymdLIjR+fUFwtclr<0`2KzyLh=;qb7D6i`*Y(+2qidzQlO|&^FFIvkYzwjpX-y*O9 zs>lWt-y6(NK;HwA<0$~S%~zbPZWAlzs7#kv`dL7O4@Dqcfl1~fjF3RE|A7Nw#I!@Rd&^(<76i=a2 z7u}wP)W#UoKA?tepEgeDnGF<~&?*s1;kv8H7xamumi*Tj!5cxn7;6dD2=I4Rz)Hoh zxR6d*(Fx!ODc+4}-AEf24Q`?}5%uaV0MA0#gb#FMCNv-MV3eM(+%~QSLr)Q#e}&3H>!ggSDr;^s#^ z1TiBx6D(kD9mEMqMp!n>>b%}al2>?##%iOh!X%qWGDr(=8}SdaoQ+My;a7SSWjMOHjThWm~uSQyg5qVFJRK<$MWb z66R06lr9X58L=b#1vs-Jgap`FNp~^)O{!!ts9UG>VI#M1WBY>-KIp4Z01HRHo%qPZ z505>2&mNavdYLa`#XTBWy{Kf-yw%S&QzrpJHXG6mK^3Gd@gexmvR|h}hbaqwo3DIw zl7x1}6`fOB2=5p--E{MK{`u#}!;e0!h3ytkqO-8nMj&}UHpsWzwr?9xJ^7^Hgw0E~ zc&0M9eCvn4J`gINas}Twx93hbEXM+?%#n!6Cn-wn@+pR|vD+JyH{V6TK~VLfBN$xR zY#sUgS>{iD>Qm!mzw%L^wD{It-x_z{{Vnl~alr-W`Hil8OPRI@V0T`^72ENb+l0(9 zh0L>f)iYstfVo`wx#N*(hZ|RT1U9tK8a43>%rd7t7TXXz`?LGFlM_qIP>zK$Xb6ak zr_rq*;P8)Kw4I4Rl(ltG@gWOZws-bwl?YyKJyv$xp5#?q+6Y?5l+V~i(s)7X z#eY6z6ghOfE#0gW?XYi-A3HI=dFMCAV~;%Qmpw6lQXY?^@=s4D=>yy{F45x+Z@g_> zd);+8=~ySUd=i?U^+kSmrEdvsgCJ4u3fI1{2>PAUY2&66zVtvWFgRkF!Ory2 z)$PV;=VN2a8|big^?b&pg?Fm9jiB*mtJ2e6cKC%~fb=p?;2ZsZ7FcojQvDfwFS+>Q zv1|8Ew-05iEpWG4PMYR3LdZi7($R%b#<``9@G3CO>Ebr!3}k@qjUW_}O{4-LrsI&H z*`|;{0 zvjtrK(y?$wQMBDkE038$NEBB8BtONV9MF?X9;u9Lw%qfIF@E9y{`&3EYvHUH4;-9a z?}6G4j8rCZhC2A**cC8-J&wM+Y}^3^Y{c(~lQYoy(Z7_F!E%*W6|H0%3RRCh;g~3E zAnQDu0bDL0jiN$Jr~@GU$m>Sse9p{FIl;vq=v+u*O1tlS5^FX{WbbD3Wsge&lF7Tt zv3s^*E^l-v4z6{93oVV`lRM>Csq|M~$#P&BQy{PffvL_Q437yb8UUefEv>KE$S%`@ zpKYAV;BqDam-d8y7BD*a=s?4*v$nrznXK`>SkC4@`Q#Jh*=Ko{Ya0So1uTNMk87{J zRudZh!`ZUZC0;ZvA?1&aKJz)1VFAKrz|5Jq32cvBk;BwAx_}HK9^}n~<}CU>DLry* zoRF=%J)t=51qt6&{iR?0#gthSTI6xCfc+Isde7c_&iIiZ{ZW~-*^}Tb+HAVpZ^rc4 zK)GTb$k?5OBxk_G(>8azYX4fVB1m$+1X~w=QrMrV`S`~_HXeWc313}|hhOnkYOY-W z;1B-bxaF2x{q|@UqVT~4ANp8mWS|XxJs{B*IEC$&qx3}Ge6F*ljFh*(JxlwEdbch` zUKu;Im|#KwF)bke>KlLMw=(-I=qr5ch(&td9Lu+EJsFaKBS#L6OE20tKKQ{O9G72y z`8dYaGvS$h^L-#JZ7clwiqZ)$8@DP`0suPb4G;oUAmunz-#&otzp+k01AfnpM7rP#&;>Rg`LI^SS{RHt8Xvw+mcg8^6g#6U4MkOD|jKY6~8fxr_YlIE_h&y zwS0JmjJujPS1%(6>1+EVQDYX+x{{v>0^3}M*>-@)nlhX*om4|hUg7}C0uFu7!+sIk z|3ytntXXxzt@uo|pM3JE@%68LeSGl?Ul@-)_PB7T#&(Sr-1?lw8;dmY`gnF~oIY`C z96EG(oO{kW$=p&E&wr>?ntf_Ct*ekBQLVPWU$FHadPOyr? zz9UbO7AV>1rC;^Jc?M|Mz!kj>tuaU_?kw_kY4|O3P1#)DQiG+ggUIE?Fa5t|F{ko- zNKA{3!sB=YHk2%O(&c-EtQUOiBxFn92C%DhEnI1@xcTpn|%}d__otMcbvdu8H~L(KSXTHctg{ITgHJkw60?) zRG*Fo%xQ#T3jJk=M77i0Pyxqrm&86+y*Mts+NNEpBzW4Yc_r}Li(bDHycRb9{Lq>N@V7eMYJb@vdqj}iFgFW*>(4q2}WQK%&$#*pA%AE9sZehbD z8LYjb?%suwRz6VXa+s+5ukV0;0Fi;i|H_ z?jj=-5*8VvX)|kp(X_@0uHe1=(n~HaY4|u>?@xg2+U<^Sdgbx_Fjpj*_*kGAz#}bb zqY{uYCD<@PkqXw8vDkq|nXvTuU|c8hDnd}5!vtrysyM31Yz=5|#fs>pdsUS#p? z<`GT6xg!AkO((#|+zx9?U9d3oEp0w&@+W`#C!W00#*oFNpZ;?A=n>yS`?arrZ9MeA z170xiJ$vss=iIYZe(8{IMD;j`?2K2@Yaq`_cIXdn3R+O)$iY0toUX(qdmfKqk?-s< zs6!tb#ccz1v(VvogMI?WWg^7EWm^y6Bz-a`{Gn}rc9Ja`?1-4;o6cojq!;~+RIEz5 zmN45BnXw^$z)yW=P|D72y18rOt6%@x_{1kaIezOCpB!KQ;+MyPg9m(7is!_s8@IdK z82`BHd-U*;asGuDj_>@=?-)P+6F)J&`<>r4_Uzs3lOZRxIL4>37D(K6UTGWX|755@ z^_Dlk+20K3gn`>JGPN;D1U#NO#$NfZ z^2#*CmW^QJ@>T@@k|+d$UEXQ$(OC7SxaC#7kZ)Y=*Yby|crv(8>69~L9=8jhd+s^D zvxm?5aT_s$7!z6e`a9xKdu(f|krR9PEABQRh!OflB_sjx*byFQTHM^P8fKors*Hw0 zIslJ-$O=vR7nz|$25p49gAS|TP#pV0d6<0ZW&6gq9rX?jL#_Zr$9#)#G#%~A~vn&JUOS^v}E*Tug}K$_BKuG_>@c*651q&E0X7(cdq4FrvkS#C>Yg1c+-9=8)XVU zDD9T*nQ*Ez=c*X&gL6zYQ=M3ju-I-~=qNjQex`)Pu~)`L7ha^v+QWWskE_F`ael6Z z@}^)8$mcL2(c%*yVHc9C<%quZ0EtJRBkYLHKvL?b>a28V6;(V*$~TKZOq4UCWJnHIP2X_a8)W|K*EoC69{Z%h z@-Zr@AgZhZ($SHhfb1rnAT)rpp?A88D$jD7S3CK}+I+@isW*@@p%PPM1HfmJXV0T! zW~yx|JGy53npWWGl72P6Ti$|00B)v_e#I8!DD_HfqddO-dF$5k@BYod9Uu9~zaP&& z`>gA3@19*_$M)1|%9F7V(T@g3jsj&b(6=lQOTV<(RL zF#(==r;VOGaoYWP%T`Xtty+soQwh-1QSX@%69&)p$gUV94CZOvf|yDmS9kf9Zn&emv)#bH-cV z^5(I7&+c)Ym;5mZOJ?5Su3C}^k6~< zQue^dzWYpNC?M8zF2;zn&pF#KJml_}JX%uaH6L!PcNg$dG5Cvjh7iIP*=)tU4os2! zl|r3~ej{kw1y9MMZ?*2Ah$rm@zs7Z51{Nd1GB%&~=f-#h$j2RHDK}SHofM?M`XWH_ zE%Ty{5PZd_{uDy!BOR#3B7X@hvQ1a|w42M=L<#47FdZ&6Hb#W9(e%bJ|02<}rbxR&P;n|Xxi|8TQJ$?#0qP4Qx28aWMnR3)?vSxe#Xtve9OGXt(6J1oT8uD z8n@(G;ySL4pkT^b_>w4XfO3&LNdzyXFFGkc^HA3_zj?&eZRGVu@Os$%-~8M^&Xr*N zW^c)<@mi4O&mJ&9(8yc?G`2>sKvx2;UjQN~1d@H0%KoXmZxA56%V{v9eaFJ_D(}5)7 z?jRE92+x3I24!_Vn5C`Bn*AXt+8K~TS~hrcV5C41(`G>sq2v=5E#NfmMmVD?y##1| zODXo_q|_4!Tn1KtX;XYMY0KDu;AQiWM*K-l?6{T9SA)x*O_ISRAAZZU-mZV_!FF(L z1&e6%W2gPYW*dz1^LHx@UET?xCum*Tm{19Cln%HoKzJd`eGlI62^@J)_==+xvAE~O zPB&|k3%zfjFTH(LV!maI4C1lTWJt50oLGekC!NH*eAQ24gBE-zxr!8dS6+76;M=>8 zJo<>!J|S`FkR}c1kK1m0WAU&>9G6IqbH}5PJvt5@*zd(h-a3v9S56qU`F3gL-FN@}&8!QMt=QYq#EkRRSE-_Hr$}8Im4UR>ZxjTypXF<~Q#0r^IsAqF(@mZ?hQSBofb(awX&b`yLoy`SMq^VEFpD_r7~w zPTq!#Zu%HT!N-=OL=N`O9?r(1VL7>QJ-9+hF%~2m3hh%_iigkSl^dM*ku%|E2%a$G zLXQm%Q`~}(lQtJ1uQzaPiaP)YK)-~gd=ZxYV2oE8_%#jnlk%i&vpl68W>4Tc)}HT# zf9VTf8o&7)zu|AAa}_tY>WfSLihjro&bS(P^zdPykb2u&-#R|@p%0B8`k^26ZM>T{ zZSfn;xphC^6K8R_D8K)~wGDF&sML(8Xd{yE+vxO5+1Z4q7(`N>-YM;j(79VRP2ro) zHVNDb61V&&6U3+Bv=uodv{z12`S$Uze`D-_dA}EReniGJ9077H@NK*LaZ-`R%{A9t z<7a@kZQrW#;e=^>%yipQ*nQ69S;>n5NkbH0Bza~i``3WQ0Tf+T)#E?Vd4$-bnBx<^ zcIdb5BuOK}ap4tb+-n+Aj6v=qxo7zK#vURc_urKN-2XjZwi!Z$7XXot`H_RL-F23Xpd+Vl;OIo3HT zU25?lEq6K|K<7QSiWAwzz7BjW6fEtTXd`E3iff*&P}bA-_t-85dn};dtngN5|2l$9-_+`3``I7mKs!o_%)gJ@@Rf z@3MTRf;TSnnHxX*y09@2pIdbbfQhdODSPqg&x=-lYq{*sTZp+bjZa_k0`lb-UmQ<7 z`nc=p`WtQ-?|Rp}#$K*gvtUL5^~rc)Tgo^71@MO_(%N{|D$iu$eJ1EdMBU?Cr4vS8 z+8JUgD|F6EnVn=m!<-HQ`iNex1^q2I-RN85o{^6?^EoY)tK9frvpql8>lWb`>TDj5 zKk@i@?6F6D1^%<=fl-XAL1e8x;kpqqE6}tjT3W^UP-?l*W$~Yz)4;@lp zF1xTF9&e|JYop2_=R}ZX`J2fS=-XM{*U-smrhMT9`Avul6gDa#J|o+(=y5#>K%p*e zDGSv!ePUX);tvt{1cTb&NtKg}ynOqYw>RJYt-Hrvci!nb4P5AB$ktR zXt?FJTgQzz-C((VQ2;Bf*Vd%0KB1&`)N>sAq3v8ik6i(b2HO-nqfCAf`) zmk;C(A!=C_g96KVgIPAf7vyStC6)l5jLx%ZosOL(dR#Ph(>kB6+j!_LQj|Hlan?Ad z#qV>^J*N!i!>m8;gO?y)c;N-<>jpxVn|5!RY?CsLt1jr8n7T@>NmB^qV2v#MD}BJ4%8@I_#eZnSyW zguot;w;KU+i*DL4QZ^@Bg^Xv*n9(OS;B_BV+M|-<+yUgW2+aoGGn~-Nvn!xzxEg(9P&@d&bvO~F~h2Ie;lW6AF z#g=?jW$*_&KaF^%5=;ugHgr7YA`ICIXTcJ8rg#H50Q@qa4yx2-FJWx;Mxgxo7`}yX z=WOkW!ACv-cFGk%toTYCH-l{IX6EYw zm5E10AYZtSJJR&fa)JRl!fIz%h{SP4Po6yPMegpMyT@JMx^sN?)1MvNck-Rj$naTY z={&9jHZLgo@t^z&O$1MALYzgK&$v(iT?=Io%FFKHHUQJO5CKKG4UmZd_U9KFP;teb zm&QE$=p%lncHh2z!tEF*PaT&z;Wh7s8(!pz*9!#2 zIk9x=)Cs?Bdhgli`KtH6eV2|)wOxJ9RhlI3HZO|^>fxm1^6WZof-7nGiUr_o*Bl_9 zx32R1JD;zyU-hR=A3u6hzS-g1?9Jdp^5@{qOKn2S*0-@@GjDpG7j@dx&Wa8<_k_>7 zNTos@2ajp!fPqC8FO{NzTrrQJvwY=#%NE|M%nO6I`0AoMi1Nrzo2HI9+2DTZEBMF+ zoarmLyrY0*>=|SK!Gnk&=bpXSZF1+Xo#T%__nGmFzxYdI&#ql=Cw!iVE0(WlyZ*ZC z#&^H#UE>XJe8V_TlCU< z1hQ#2jewT?i9le1ffc-fG1*my3gdSfBje6H z@6w{?dDjmw@}sTgML~QXDYy0_0RM0$owoLtx4vaubkT+N0xbG!PM&(Kk|Lt;*nBqH zpb}2nFXR)KC6s>xGDs6@vv0ry@P{#;U(i}NIU%MFbNp0#B2!xBC&{@|?B(YZueLk( znL-h3gIK_#pFBoS;?B3sDicv{%UFQ)GF%Vw$CBs&H(+}OQN?bpP2kwvz(6?k@rZg* zK)-tKnPOUB2zC>D<%3T} zfSi4~j#e0oeypLUUZ12L%|vAas%243YTnl!kI*oGtm=hL*Ek6 z-MFP4OC0goS>>=YwwZp0GvOPDKLV(T&b9IqMt9Sb-$4G7Par?=5;erd^d2W#=2}>r zSF(gs3r^I5%6(S%W~H64`APdiIxIzs2|X_rXPi3+b_q96TFKB>v@VYj{2+9*R7Ui*Z<;Z*4WzIooT5fw({9K|SaBz@ z0bR|b&_*?YhZb4MTD8kW0wPVDWaO@;^-fTu&szKP zc^+O|G+lWW4bQr9WwHgE)*yb%SfmY0yMQjkY*>5&fAGl)Kj;7vWD~+;CdDC6Ir_6f z3^-m;DQhc}cs~pL%J}_H{oZ)wkw?ciEtEXOS&wow$vvut7gvAoxZ};^m=4ylC-S0$ z5Fkz&lwJm|+5H==lmKYONzcpIXlPm!3HYAZRDl)9o)aGN~ z3z%dp&R^lY_(^WDDXmDyk?l4zWmYIy=z2AXdgRxlRxlZ~ZNw1UPd1Se_>o!*;$yimm*llh3pukGJ}A zo4)0dv6StQP0pO+HrU{L5FpcN>2W)=4)G{Tc~}%~-@4t4UEU^5oBF~RzA)~+=UzV( z%=7e=aoaZ0h?X+CE|4TS)IAG!7FiZ5(JbzE@7?2DZa?_JAMlAL+974)>M6Gu`VyD^ z^tsq*BmE}>xyO&696NVxw;z24o%W?NRj%wQp9KjT(=gj;=t_d#amrt^u*dBg zT!C#AjyhK|Z9gQwx@r&&QSvN{%+!fbQh}zwiq0XdEAhyJEa@4Hvz_p6 z1j;izwJ)0Tb5pMow*imVY{(|4b{APdhYK1*Y>2PZcIE{mAifs;*M$x2 zUBxZh>g0=pqMQ1ZZKw!Ybvyz(#Q*SxG;w$qY-<47U1t!nb)Q>MTMlXLZJSB6p@*R2 z2HI?72U>RX0FqPo0R%Ho+WZRbihtJ1Lss!E`-^a$Zpe7oOIdsvxzLEx`Lz9>f6YFY zO!LYT@mzE9*;es7%&=GlFDgr(OJl`fjfadh6-&I>luqLlod;U-dtjk)sDe0x+x6g) ztLStvRG_?B7a?>aa^=msa)u^ym-bq;AXGD?VWN*)ILWP!rGsG_5%wiM9~@`sGOUHz zJLg-Z$ zpRzb>$5reU@3gNx@p+2h{LSC=XL^`;^TP=EcmdU}UAxAIKl~vt+DOlU{Iap2%Zr?f zZU}3ALz=-5-|7i35~66ZjRduMs-uY*eq<65Of;Xt9yc&Nx?TPkt3=(a1t(yB0WK{j0wkzx%tN z@|8|LQ-d7DL4)ng^K#XV$>S!UoVe=htGzJfHo8Mc4@d4Pm4gMD=rFylWMS8zQ%c{$ zpLsFY+OjnCm^k}?lIFeponwNDCV4D~{JgUWSp42|&wW}De^CqKyT?np<1NHjUU|j%FaFE_LW_vA{ZcfDmt$z=!Z{#gv&$^G#7}A= z;<^A*sKf$ee(2p z_q)Dp{6~N9?`yJsdK^7|OupudWv)o#Bx#G-~DPC5@Rce1XTK?;) z4vdb;e7BJx6{jra1NkRq1PD{E8ALyEZUo4o{gK;SOG%$-xv8g?pSB$U*Y-57K=!#j z;PW>P+i@*Sc-EJIvwG?ueZtKtZEYjac6Ht= ztfg8Hv6c2>K(YHT+j@B`Fp+d*>ATnPqxCovKUMnB;e+Fur=C)oIq8u$d|GXdyT~{( z0ha7GXfm!e zZ4sCroo?eHbh=@-VXe;fun`SnS5T8)qREKv8Iqi3MQ+!vU?GD%A77OW8rseazhS|n zNXZKrZBj*=#L)a47gA>-X#cJd7j*qD!0l|6Hg+O!4ebVyo+$bx4Pd;0C1SIXM~*-d zq8uZdn;7~qgUnuz53$UuLQ4!`c5zvZMSM$R{91FU_)B`%GPn9 z^9c*@N(R@o0^>+87SrYdN*1_jLc_L^T^mCtLJSzI9UqlZ9UYBdLg>kFy^ZTIHk6g3 zSomgLM}c;czfuOuo{kupA_8QvEy`;H%8%C5GMD-aVr<1bpA!&-$XG(#xP*n=NmlDy zTb?yA*%mhZm8(M~PjdNLt3}AC#)lrdhaY~(&p!GVM5Vc^ux-mWzwE@fN?X)=-O)#k zUF%x{cq=t+lVM}*>#~&~*UwrxSe^v{G^dn?!-JLnEUYZbKG-yNZr?Wk__LoIU;pMe z#?BpDfO#@U9#_#`@gnBUZ+i21@AtgV&kxVAsQV3JSr4xPRfnu892Kj}+il22!f47X z`xPde^NT@v3(uOPxt=bnAecO39pCO!?~m)|VxcD+d-2g;XU zetG<#{`3Fic-!0G=Ff}7E^NspTa?1#u$)}j!eWr;-7S+(Pi?b3UI0qxDN09NIw+2x zudTkmx`VKH>85)?A+P%~egxb7~wpa&#Oy zba?#N|L`A{%Ulg+kw#vwwDaxlpvNO^o(CGJpZi6Zx*{JP8=V5 z_U;~+Uw%d1QVJ#G13r!~cF&-!uAIkUZKfZ8Gg0 z9rJuKjH_+B?SXEY4jnw}^fmLVfoX^==vMd?M{cK;m*kvIp0P&F5dXW?mc41K6;m{I z1TX38qa`ysTDJJD0vfWBhkxKh5Xo6~g0hwPl-Kgs0{EhFT{k^?vfh|s(XLkTfbvQO zcKH~Y4BNwdAOJ>3h&aS$%m)&oe3Z++(%w{;1oJVEx* zR4fK|_8MA3N(E@|tRfUZJD14_PpT%=8d{p}ioIq^d5pJ=B`pIS5FcdHQefI*04&$c z+9MO|OTYP24r3N|IZJH%HRY{a1uIKYd_LPnhV@A%9X4ks6*4JNPRdKWfERLh0Vb*u zpu!Y;O8VnQ9*}Vf8uanY}ebpGeJ!3xou}S(&51^XK2N)lyGC8-tI9p&w=MxXQ%f&_tTULR74*t;zz?Vtezim?|}oH62RwfhY5)96=u z?MHc9aTaSVv?w==x;wvlrxzCY-g~doTG*XBsru4ljAwnfZO_#>{Z48@!PVgZ%m4Ym z9B+8j8^?h|he|JgWs)sBRL@MRxka4YPyg`ue&2rN`Elf3dDT_EoqF%?-D8ioUFxTP z6S8#BMmQNk8}P{r$^b|(jz8%VUT!G~_P;5hDu8?yz zcB>Z4C7~|<*$Cs zfkz**2zzB5Q=era_TT*6KN?qEbL}{I_>dROyvf-MH`mEL$>{|#VoHh<#YKR+0--7U{jBL z6Z_3?ee<~Zq6>YJfOf)N0bK$gPwkrcrfqdh>4jVDvAJH@#a;&mX`9&_EF`|4)7Y8h zgcsx(*_@3}P1(O4$0!Ma+Tdhxv6qv2oBhZFcPnrUFpqKU)?$xOARz@gCdCl>&SRj3 zcMhQu|KUJ=V%G#McL{Tw=^VzIAk#*=-7NWM+S=PEO-uQZGWR92q2<#^k83>QxWvh* zy}S2}^Dnw!Y}v+3DWPDaJ$D?49foyf0-Cn10*HssSnVvnaZ{O^r}3fdF!-iv2rc-u zM`U$tm~rWoGk@@cYLCvL{g=4-idfMJW;+FhE#p-Hl4e-}^W)3X(_*#FJWdg@-no3C zvF(a1>o_)=W1^3of{t43T;495k6{y#DMBkG-Lmjm($vCzePPu7mhJzL=ro z@FSZtDpZ->Hp||I#N!1{@Q2+V5et4&ijAFfW`MPtflow(xb~vgZ--tBwFq7Ul_t+s zg`62GZ=$P?=?09*QlM(j(D|XY8lvPQ-)DL@hVBHbfZQ3ko@S|c zhFNbQd@U;(!8xXF)vo12-sDz;-+B=|AqC|Rg!O>z>}CBBZ~B52e>d+MniadqZ{HJN zLg_L;TgL^i=PZJQYFa=(kY3-ONJ{zY!j5}Da(>0j_s}wJv6d+>lUZ&-}Hm;(zX0NBd{ZZ{xPhV$m+W12w!{vZ6| z_{vwlGPdv7;b#shTPEvjjlA5+iyb7W9^?xah`hw?gFo;C>w7c zb3A2?nQ89<5N&(fzVjUhSmaO#_zEAg2;;eAKYMIis0mqURa|vo$tnk$SqO65>FLuv z(|W*t>A?pd^ewqhJoV&w;l-DxXPQr*JmD+A|H(i22V=|jExxMecHdPg-{GFEekS^? z@&EaM|Ig#EzV@}TWA`pUqnx*gL(VstS@g2N**?xW_gtqram5?nckkNeesb=)=lgR( zeEWEtCaLuI&AhbA<$Y!BP@TZX2`1!o@`&eR1G0<1Hg4~?Tb1DXW!}X6^fOPZul=dU zk0-U*J?up=&+ML3J7sZtoX_RpAu-ZVH*eYIMK3~g5{1S>w%P!`)xcydX|-YG96PE- z^ouW#cf8|m;~)N4|J69G1vcOA^>eBo*D=Zx{qiz&@ong!lNYG62sd+xpJQ7FOW|k- z*t_KHnCMv$PvhB4@$G>9Af9j`BW0f<`Q8Y8>?s}Y^Q4{7UmKNTXt_06U)txo+A7~~ z9#1{}^!S$AasGOMPBE_M>`?L36>Hjp$xqSc+~I7 zDk=8Mp~FYUlTSVE6EKWDjO&+Na?#j(_MZ4oGF+n;$#^^K46>#DZvgvsDR(_|dDkyQ z*w#80oMcuog|5Sn1MuP7nUJ=RE>031^~tUM9%p#mz;`TZ{G% z+-$RbYI;(%aihO2KsEG}X6o>a0#bjSKerinGY{>@$9CHfeefH>q<^V5h{QL5CG85I zL2;66_(?X|S{~x2Hc!_nfbG?0p>H82+k6!VR@2B|)swc@`K6=eO*U0JA^8v~(rkvd z5oBkWP(V6)kx3kS^0BWjD!IL6M5xj`mJ>8HEX`nCOIjF(oyKm&v2!SBo`}Para%4q zB6tI+XM(%o0jacfIHKCA0onOJ$bzDhq3sH9hYMKvRGtr7&Lb0~1(I1w6B4O#hUBQD zHxIN%lJ15GtPTzUaT?)@bn;`g03J}1vA|E|SfO2l@Z>Ac*~D!lP~}xBHn)usMwabz zO!&ouI9D?OPTUKOxOoBc?Mo+Q&ZrYvZ66RNOiWFB&|#mrAaFzxTcG9e3PuhbGy_#U4AlT?eoM zMivB=m;BHHp~DC#inmY-{l?~#d};)n($DC+sT)9PMGzSuB8c|KK9ke!nykL?!VBZ+ zC!f*;^yIkyrklL5VIgE{@#XBM|DKrH7WpVIFhU{zfgti{Ak7Aijc_W(r;UQ5J<-Ny z|C~^nBAfn2n~I#o&1_rPc$+c>`m;a#^YJHt`e(A0Z&CB|9c)sT-&?iiDrNl2t=}#kw?aX0|&?M zy=RYizvo@@!`5;9ByR(^I0NQ*K_Vk|Zr?E;dHA96fBhf+nHIKZkFBz&_4KE1sOQ`z zfPh?O_LV%z!LQ`=Ch0BGg*_}lX^-2saf>>2c$TjugQs5J|2N-1uD#}3-ywmo{Y*Ac zu5OHN8_XGN!{bcRmmaq<;i{d6FEjyk zVh8!!!lpQpnHK$L`RW=_dDf?Ls-FF}Q1Jn(?p;KTM0pF{H1ciF{Q z&)An5qMZ2br0d|EbI%($+;GF#cj>+y7kH5v^@&M>oPE{>zE5 zM<032$3W8P;N;?-J-gKoFSTwMTrc>7<1^*5De^DEl;#)Yw^QB%8&Y7IYtjbr3hV$v zcG4!=x$Q!O9pDtLiD-nUjPi@MiO(ksoP#a!Qg`H8 z#0*`gsXR-_2?+}|**s2^P>_bXZzdjq4pQnBzb6eJCysM66_k-BgRsYyhVq;H@~ks; ziH$SPHrO`Q#9ne&#BB)i6R?!mU^x>W9SSNvm)rX_vFDJ+{QB+C>tXR?EW6LnO=aRMdr(^g zcnzlH<7kD@ho|%7W9lspS~S6QR>?PmVTIqaCDS>oSktjlk?4bj+}W=6w1LPCEqrA8 zU}79{A|suw@f-0+F6qPx$!q?SN7B)j!NEK+7DO$JgWIaES!eq+k>_#6XYAC zv_h4kvu02Nqr5d(6NlC&8yqT%Ltt zu79CmAWOqgv?yU(bznMpY$Q~gL83bLmaR;sWd_ujk5Z~xBkdI7<0lPp^L$|;j< zu4aAc!ynS5X0Il4$Pd3mgrsl+bR{3(LlvJbZEhS9ZHoA_HOE=7*C%0|kF3@sQ2l5L zGsW=(GQjT8V)x;P9vq+j?B~XjW5;|2@wQvuFy8k)-{UtHQx^J~7ry4VW!B9vKC&_7 zt^ss5zU@(H^56+9at&}If=M*;p@hcusD!Hk{obJEIZqZ^d&a%@-8Vk-na_+TpL|ji z&n;Ta?}!fB&lN}jImo8%aRr!LG5G|`JKy zPLTEvbJut5T#yL(TvL@1(yA9v{y=CV$iXgSp{Nl6NC-Bh?D$4_rFmwWNi<~mjHY&y zMTP3K*d&QhC7rOXK4~I<@ad@sAAD&1kN@Ids4eX9m37nO zZ1{&Z14?PrW3xia_459g$7PpYI{xc_^pCvA#YQqYnd7Utv?npM=wYGG=hgn#fBnCX z-MexeA@15$)}G{&-skeX@6FVZQs62#^w7i8#mo@)3`)& z7TMh4!BuKs?L{(Wm*6~`tjQepL*b+=-wBr=Y%^Lh01V?L?6HqFf={Spw++#H;shnK z^iTVVk}!Wd-~}o$G!L5=QnKAexNw5`U7%T2KCD%HNNv=S~gyN)m7uxTW=j(wr?HBxPw7; z7tz|GRzVg!^(?Ix+u-!KesmjBct>+0P31NUqWHjiUEVW8(=2K2hvu`6_?pIsdwpVr z{z~JMWuYt?`tjy=?&HW+aN#}faFQ*z^gi*#6XWo~!yEA@C8009hl3=PPRF*3iB8!AW8=`kXT#qOCJ_~vb|wRzY$VYi=c=vt zy+TVCa~8Paa8$b-p@fr(dGo)H67VUSc3hyo#`|fI<9=7|2HI<0e=*iN*!*)p|4;sD z#RUu?ab+48TRDCLJdR_jXgOD*ajuD(*6bbc>T$(6qOEWO>uUZmPMqF5SQ}46>s0TT zKyw2-m8BV^X4W2<%R57GK&X=p&c$X|9m;v&79v865 z-v@BhVlL?^KeP#u2}35k_NOQv2%nP*(bqPHTM#xu@UIPRL4n!A=kk;Yd^Ouh$jGDs zI}&K)N^8y{8mWyEa!V_>fIj`y)BcvBZ&ek8%b>Ed2s?b_kgphBef8D8VjDon988h6 z5v2;-F2f40@QVAnQEu6kYspH!1vwqST5ySXG>gnJKCMOLv(LZaMFv+LdDirzi!K`H zoqxW{gUw88wP4i3z|Y!BaLifi04m|kg}xO~+CH!N1gmt-%_KOjDP^F(IDi{U23J0h z9^)Ih+s4HgU*gXLvDkX%>8EX@zfsF1RJ5@f`|BXBA6LD(YR}b1p3A%7{0n@CLfW*r zV(dD=s$RrY;0;J0T>2no0FdhinkRUwL-i-Dp?e?)ySz})kK02hd$9)rN>eXB*@Zj~ zmP&KQjl}{B4!%jtLXrYlt9W9gcW%#ENc=pN_r(`p9QWLFk9DxvalO;etrNe)pYkxN zN0zN&+`#UV3mv|uFSE$TM!$4R8~uaN2|e}XQ{!e9o|jx=8%d@P{?QXV$Hsx`ZvceP+g|tl^S+@ETG79}q{EW~V0*QeOP?P*;43Lzo zRZ-fOiOk&NdnE-qF_r$>K$`7I^#i{5&GYv@aVl`z6YZs!?i<^8ZktUkf3WKl0|34y zVKOHQ;gIcrM{t27*R`N{Qj;~=2mqtkq+M4Hlqr4MG}@?RfXAiiTb!(GcGt7~&F8Y* z4jI#1N6T1&wTNY!_-r@DYTbW5K+ak{OF%XytoAHYb4-4ib*|K3`MM>CcO{kR8Nj&{ z{Q{8Lc*b}BBpX#eXqrMBj9U^b?mo$Hs#a(!Dwu5sO<(PJ%EmYmnktj?XB!EpxbvHC z*^aQAv9=NsQspDAEeKVNP~1&Lac} z9WNTU9P@}q0UCedpa1v&9VD;A42vtl@t0j!4HUQejI`rG#jB$++-t=c*wXamD@b8q1I|Qiq~*GSIW5~b z-$n2JJeaOxRTAraX$!IxN$JuR`Idb)JEI{<-JI$A9hDJOTELiJ-5t zaKL6k`6EB_BTD5~${A1qU?aYXY}XH2wu5y0XaS_#uij^oG}+hqDvLikr2MWsvUwY@ zRu1Fe{o7yiRbXC-L_W6@^OC9ez2|$!_19hFTl!AO?xUjNYGG`O2F+RLVs!f?aC_^_ z-pD8#%Dc9oDa2O5eG5QXizbwUbFb<;xugP+ZzuoS*S|In96aD>+7BH(;;T|=GvXB=FR0;U2{L`v7Foo*uJ!lHte~AH z()27)InnT+{pbJbc=H{1c+pDzoj#eX^S(l%x`cMewk(+c#V`Cz35i^;`nxP{Cl;=K zLh60n_N}Vx-Q${Tt{vx|cmBBM+H1$|-8+4Tc8 zOWKsrzT061X*1jva*E@Ec0 z5x)3WpxQ#~^|;^+$VJ~acn=_>b);P)*X_qXrY@mo?ASc`{M50dN5>v>tYC3xKcuZ)vhU(?)6F;edGZs-)fcC$ztXO_7nQb?K(eYnCUXQ{ z1j1l4@la+6;Nwbg9IR}JQg^8f(gCZmKxjk17FbUss=3VL#cJvnNFMu*WuViWvh5%F zkZ$wz)6eL*@qETy`HtfP<);l@dg&$O{0q*H?=A-iEfL>v>^hV38&$@-;wy^U!8Wu6fHgY_J>zKv40CErOl9)W3k%A77?zw*50u zN1>gCuZKykevwlM!K^1CRN-JF-sufsR=x)CL)Ak8eL3>MldpvNsk4$p{v?hB+Zrey zw;zwy%lQbh5rBNcP6Mm5=JJx?v_-AVjNjoRW(|y6jAdpNjruZUn@{(D|XwJ^Rqc!J$&VBEio9 zEiYzChh!j90GlU-Ef+cm#oss!1nXb$83<7}>$1Q}HmQb8?hrH6MlSf43wMF?mIFd` zVQbPrXvL41k{ddJ4mmGe!miy!8@jb+K&KaVHK?^+KxnZSxpR3uK{YwFlI5JxpLuW# zSf=upxrKUdu#M@YPENiJv|Yi+-q(_iB->h(dmBdFxYCngDi_(HJZ*zUGttNZseGws zaM?s%`{lnNlxZCRp*G?A0NeKd^XAAN3o<*Q#Bd(J-3 zHdFT}wcsLtT#Lu6uey4C-~->UH79Z?Q|b!IfJJ)(2QG(wd|+C#ycdA0i6sVEhBGIM z0tSD?A=BQN7Jp`CP?illw{IVx_{~p_d+)p7&yo6Mi#8U1n>TG8Kl-CTJofFo)Qb<7 z2XPGWlIiBsS6;NeLY#axYbJJ?tVYjj+l^%l<7a?oEp8o{aiaACk~U$qbSc39Ty^AS zY`^~pzds&$@F6YWcjn513~w4OXOs>P2OdOFcHUfm;l&q?cfadh zeG3x@YJRj!xNMH(y18MG{s?7b$pnA}OD!I{C^;FO<3U{Ps7$Y5ZsZ*?;Oue(sKdicscYsOkq! z__&(`5Y3`7UT?UmU82F9Qn7Vm9^X${(S@kPUC>hU~MR`;&mujp%_xy8wXNTwQ@WKip zUw^+CaDo_Ne%nYrQ{T`ikC4JmG)vxBhb6rwlpNQyV{IFLBB7n@l=8Fr?98|eBk3GA0f-%0!6D@4T;IQLB=cmrr=PzMNE2_4Wt;)9&2iB$+ zwtPE2jX$WDg+IkUiB$-;=^9>D_QX8H3jId;+Gc6-6(p-Flpt-^Rht|7m;zW0k)@#0 zyP@r7Nd63zn=oysBnn5})R;BlvB}vMmHJ)gPiW$?Tm{Y;(6|93FINSb+EM_Vo5W>%yS3}9j^s7 z=i(7J%eL)*9lbS)cw!y0@VY^PfuG^B~+Qxe@F!9$XRT+7Ntqgf-zduQV(rEDj1 z@WquOimvnetnPLQjqw2atFbL1%<6?*b%dl3Eelk9dtk zEI2rDTBF(zpH0}Ri5IuHHeZ1DytHo_Uk{YC>#<=Te0l?{x#(xSOS$w zPmUK~dO?fgU7p7UV*k@mKRtfC@?^GRk_fzgQ+Xjlkv1uT>89)ugZpLIDi z7y=gIJkm~7xJ*kz+hjC8eP!&}x@|o7+;ihse&v^i(`1)#!%83LEs2|QW)ABSucgPE#SU56?VC&nadAl}?8Q#QwSR0=wVxi2Zm3S23 z+2@~=5AvxOzO_pk4jwva9~>8s{>q!l`TWiM-~aw`F)u=50d3p)R~=xa+kNcg<#Z=i zfA`#dkA1vv-#)i7uK2QT-LhRt{3`o3fnWhhd+-&1$@T)0w%*4cmtXnB9Zl%=NJUNl zBP>4`WPA^O+8A-@*3$;pvKt!Le1Tl~Nc}gB%|M?5+v;@e>*EY`iJJ<9V6g~R%J$+< zC$!ODlc6|~)DyQd^Ed%zqV)sFr7d9J%li+EJHPo&j}@FSNgI|3-qgE=M>43V_?&v< zYBB9)@18y5iYqT4H(Y=H*rhm&V<|Cj8|6|W&i-VJT{P1yEN39sCs;&lNcz6pB{&Cck2}JI-9Ui*8LxPu+kW+zM;>`lc+O6w?3Cn` z#+5yL_xQW{OoUzMlI7>eTaePUZQsGO0`wO^1}$_44+2=jgPqluSHS#M78=4etU%fc z87-%MNIYXw{3R;mvYn)C8b7%OoIDp(V-U}i^M-LAL-9!}(-SV0n^-8ywFYkh*E}2N z&o+{eJZ&}VSe-4W6~;so-O*Fw-gDO zyc1^v@|TPyr^*!_OMqrornyz#mI9#G&AA|pT9av~@;a_PJ|bmY$*BIMEH^37j(H&pOVSF}ME5EtJHt@fIfq+XW?cL2H0 zs5D{AUg7{~6`wjw;V06LRQ?KW!HTX0Y=oc6fDAe+G$qe*I)ext*WXd{yW;{mn*$W5 zpsGb-(*qd{kYz#1S6=WFS6e2d}u;9B<%3#(msHMXw6({Z($?Plg83bi`}V(@7KTnweh*n{qfi=-+Dn; z{48>qnElWX{g8EY<<3{u`loW(hoarAX2O6^ey*}2CiX#)XL&;p*oBH>dn9BJtgn~g zn#s+>KVDoGnfQD1DPs?dap8DV?T)Qm#$%5?K7Q@je`7rT%rj%x?p-2eKGGuT!QZAG6LM>iU<*`AuEC4B^Pq-okGR>X1-ITXo)6ck- zInVf0Ui1bi-((8jrJ(I&GF%sHZ3bekV~RSfXlFon*=2(8#0Tjs7GZwcEj=^BTn@^G zaH1fPVZ1iuQxN>89%{MNC$}d<0&oSBr)&ux%a}98lVAM|rkcX*`WB zlYRslFJH-Locw&~;YZ{nZs)C+yeW^q!*Frc)mP@(cePdO-}ZGIl1$n>pNyhTCp)dm zJJH9s==_sNsh7s5O`aJ-R_$N|Xz6E?0$;|3LYxUi z5OZ7NdRVog=@RC6QfbEtEw)BoveSx_R0_M=r4D8rGUg^80_tc%JVB?^He#Z8g77&; zofbMlWTm*|5fRSmmI)2iofe<~CWj!{DL#=cXkQcNzVCKn`)7UWr_p2d5=^F11QUsh zmp%_Yv^fzQM$1*SY02TGd;S)^;b!4oPD;y{rZW?F5=(`X21yRyh?+JcI& z;D8D5Ah3*Av86@7>h#tnA`c$bQVm?yMHXdH(sF77V_0_lDyOqRNG1vW(ULP=BeZYljifajG;E1~JCJ&@lgt|+-7>W~J2X=kJ9rgvBOtfz@VSqRFTB8u z#wVV9%2yy^uz1n3zgKI0_AQY3^jR=hq(H~vwt^Uf4%I~q*;?RFCLM|s4aPY zHO32Mm5X`;x+-H=E2exEoxlZK&;)Ep#Ty_&UuW=~Ot=L^h$&1I{#Ru4$#JeGx`{Tzo8Le^Sq!z*0$nA>g?5l6IcHS^eecgTc-F^=8+;h(v7hQOv=y>5) zo{_b3>VxsYacwoB<0UWtF0N#5(PG^8SKYC18e>8A{RF1W^!G9G_61l!>d~9DM!KE#YVbzA~(GaYeTmnA~#A=U#j@QbJA(hmVm- zJ}*JyfZqKsKpZ<`D>m33+nP4TiqC#RtFmdcouqM3x_Xq#*{MaMfQ4VR#wY)~(xo<@ak}|EuwhZ{9gxeDMX33FP%; zop#h^%*(IRXE-6k*l_brH)sL;ma%)!ZZDKis{U+G`NBd3ku%EzYHlqkT}gxoG9l~_ zwnCAIUhu1JYdx4vH0W;8=mJkTbEjP;ta?xi_Y$!h5v-SyJlBKLj46DMjgzD&Yn&-o zwbPSh=Z;Z`BPv4LBGqci-BKA_mEf2kegKgL$;Mqel*&->zYyDK@SS-Z`_3K(bQ zov2_fadf$T5W`qIrziO+B)>6dqK72oXv2E>V4UlIqnP>4rJqWPji4>N z&4ucQH5 z@xbR>S_|h*okRhsq}U-}U>SA0$5aze@c8JjeAHJ8{do{gfVi5*b8@`Fn5&N;{?Ld0q9(umqw0&RS%(iD9=rGyjH|hP zKIzNB!9H-iYJWro(K%e^MLwzUk^)DB_8a*u4ESWtpZw_`k1v1a%VYZvo}bN?Jr*8E z4j&n}zu^tzz2Eyi){$?>X2DZRO&c9^8o&lpDHky|^cJkpSALao1w`kUG_4sMxRT)8 zUQx}}F2&t`WcQ}Cw#etgv(k_cnaFQf9X$TTOXf0;QuJ;$;7gs%x$-QhmEDzc03K;fbVEbGcJ`8D8t`nYixWc-<6weBM>K!k18&;9JRxbjok8DC6k zpU^&LIZ)Ea7+V-4d5)S#2+&&s#eYiv-8Qbd_IlS7C+eIp$aCOCR3?$5lRD)&;(2o1 zj)I2`d~c*vWvBcC)6wlq1s8(wNSPKc;#8q>tQ=6NY-iIeQJy z3O|7CxgL_;_1(0UZ+n-#YwLFnEOZf&oPoqr)+)rmqA9ZQHht@*E%#c1WQ_?*ho6mf z_&jbX3b|Q~4=+4Eu`e9FKAB6N+P`bkK2cn0@?QT$(t6nZb3gy{btSkeWU8=04q+QX zVb^3*5vfQZGG|=t0H~rRZ9>v>H&ocs71~v~NkyIz4jnH%0PD;jFh60E|6lh0!%vUo zI`746fx#eSv5U>v%%v!jvMEZUB+9ZS*$S5JOJ868q1Q?_NjWJ{iIhZAOHvfW<{XgY z41nMBeV#hq^@bS?mb;?v?}KNi->y1!Qk|-(vy7O`_V!6&Iz8JLuXH?rljli0fo`aWL+J z=W%GE$H@%ZY+f-*y#vR|iKLwn^608I=`HvwrTk+e=DX=E7WEgo*yr!rXP)t-_LY}k z$s?my!JX{=?Uh$wkzY5b@2ydJTP-`>l@evPOsZKiPzQAP zY$2iIgVsalaa>-@=2e##dme(=H%+t&3h*U^2@T7{@Ea+1oE z2;8+`5&iw|f6sT5dGqk`6Ze{riEU1T)Rl;KNHz;GC|Dq^T{_at*<%t6v_Z^yNTT(m zKISnC3O+am9bwZ$qaKxyJIdg*TvpX4ke-i8v5DaCQS+y??q^oS?gQ5PlUgFUdb z%Am)Tfv;i`qJ6Q>UZ-4mL!L>7_VzWh^3Z;8hnhRm+_B_wXCC1`z+HO$v~G6_tFbD{ zkX%6wYFEsG^Vpqel&^9U;vpH@i10BE(dnZj zK+5i+QYjX=j5$}e82QdWe7k+?`RD!Q2gfSEA&n?^hI!(FB8vNm%&FbdkEm;}Cw+-LX}p{Rm;6*Vpa?2kfoNSa`8xo%mSM_7 zj%N1Nm$}HmSm{27>yWJnUd35s#rF1gd+DW@{nmM2%IB)-gV^z={imLOs__$gbvJ!J z6qHb`V?VL5oykx3WvghUaYT6za(IisSlCy3H|&LH0oV>0`(jqHvOSK^jJsS&qKy9Z z{(EP%z3-o=yK?2S;=@x2{rp$3A~xyoyO~xf+as+I-o^IC5BBT$gGhb!n8z`}{Yv@T z7Yz*lFVscpd0bd5bJ`tK_1C9EhrME<-1@PXtdo{2LhUTAboDPYQqV!V^6ZCl%XBR0 zT!s7nBsR!F^ueJW$w@(I3n<^#7#T?wS}?{fAYa>9PAofZD)Y{Ok8JocK+O1bN}t-} zUQ+&p%L`zq8DApF2BXJK@}9(me)mrBD*B7D5~P3*#1)G|f@~fSu1Z^iMj~AUZlN+c zz&!99T?b%iHf&Wn7!~1z^5*5Ect?IXm_&{K3LeOvaJDPy+aSMkK(2?YxoCDhMt!$x z0)}7-m#w0aCyt!txa8fblTSscHVJ<~K~Aj1!1OBmC&XfG@VEDo$=CRq_PY}xQx&SZ zgY-KlRq)upQY^+;G!btmXR#`p%6Y1qK?5}lCl7PosbA|5Yw?l&jPXR1@&GzG4nD5R7Szut7zpUg2ALv)u zt%kBMl;_x-V@VNZdVW^4jn%1rx6fD58vIR zP5Jo}9qP>I$U&RJSh}WTAqA07nmA!5LXL`0z%ErLr`vA9s=6+v6*B9x zZ#o#=*4Ph+_DbnL8bGg|Y49qKtp2Q9u>Tg|gR-8ga(GR_>3jSLHrazZ#z6Su6Bks~958IMSISv?GQkV7ZfuSv9Bi~97$w$$^6s$r%lyR9LGNsdcg`0jN4_V-i_c`! zKG2Zqu_J3N%0^XU4(gn`SmS`7a^t6s&YnB#$8=wP_0@Li>czIXf76Q*`z58sFn4Qt z5+c8$oX2r_^!d8?Pd)y4`>9WVx*a}x*iTZh;IY5mEIf?s9f6E(Ki7y{Zk1{`kWX0?&J0W;HMzEFGEiB)FpPE z{1Aac>~!ZUZA19RKByENj6L)p7QS!3`KEjmuj0yBdhFOS|30!O`@IUT>r|i0r$0t> z?b)E;4#f-LuXOgd@;B)Rvdx3bdw*!CL8J@1wd*YjNj~|mL zd@8dO>DN0#dQdSgfIY61j0-E48E;6Xt(4#;aH7N|GehhkKfped-~*i_dOtVH9$3^- z+Ltshfw8^Ur#@AO_{TQe<{SY>iu57o)WxNI7~$d&c7fBANEb++@tp*7rtrX>bF0e4 zYZ++v6DHCk>i_PY;PvRg6HGYS0F5|y8c=a79#D=}g8Ig(F7ZIUyunT5s9 z6}^>?Z1iyuK`Y&4M!y92gpy5ia-&c@)1sj>6yqd5>sin{$q%#zKx0#R4HgT$RljVt z5CMyFKJ1t;@fa?2w75 zxZvZ)+Bk;A$BZ55z6<84dI@|^Sw6^gBoz7(jkg_hu_S@i9@Xw1)Dylu-t2yah-lpL zx^neud;a<7+n@c}pZg-k;UoOa&H?!mIbYn8jK8bqiN!sB{FAoh4kQ;dPM*B4ed;Ga z(LVRNpKbT4@A9}iZ!@=D$>ou4W$d~>q{DTxfj(~Hmn%uE$cknGJE0_bC0USrQcMPZ z0c8d}&^q0D5E=`3Le3p+BF0k|R&Dvn+Ajh`FfA5d;$f|#*Oh6Y-Y_PaH zcAIFUj@VHen|ahU{ls=PGhkdu6Ap6ft9-WZ&h?+_p>h@*EKHb0 zPfy#{|Eh%)*fRxm~4*H~OQ8*xz%L7{oW%g1*$-sOUM5 z;z;o-N7m`YnDV4UUq;C+?^h9BWow3ffZUI{0KWwH1^gC8{hM(#3j_Mre#NJ?*I$3V zoxgBFhdw@L?B_e`elNt+Pv;Kst!=4Md8yQ%H}yJp?j!22lJQIYDn3e8J>uFJud#29 zF^sH@0Qb!w1%13S$_D$sv9l@H$Xyhhv==dW^Ub$>j;A7dg!D!`a^#2>!H+7BTkX}C|%;kkrFrJ-_))#Do6BerL#7x5sXkH~ny;C!<}2`cdXh zoZ4fL5^E!I2dH?D@k)QQrs`Mr!3k~4Z8YYir@I_X8QN%}Uo7>nzPe0gJ<)H%6CtFaW z7sqnA6b(|@isYU#`LPQWS1jV^Y;X1z9V|S@`tCW_@Q9a5bn4sD7ZwF34g7?L^=hKE zao}J(eflvkJb0-M6AbS5fc^LI*c6&d+tQ%rHte`v-6z1;WA2!hj=3FXM5opw?dr9w zz7vq2$q`-ljvhVIzWMdPYk%>Vf8CBBKcV_)0*;JyZf{+0S1(^_&uIertH1hdz6$Q| zOL+o1*w~BT-5!X$i*2$~8~MAuYU{pkPjwt)ROU^;+iHv7`@P?5Z@>L^JIv2MNjLq2 z1@bl3`Imn27uwJL{4aPRjEQY6`uKfI7MU640sThPwkeh~)-68D-{PjUj)%${y{@MB z1tb%FzU#!~9awhQ^U2$-{ryK4ex~r5m(B1v^tlV?+F$?WSKBwf`Azl3E1u~4N&mG-Ml$^ay}ew3H^)SdxsaL6 z-Spi-zd?9EL?*cUlmLrP_wnLYS#@vIlqOp?Fv&;0=gEKQ=5cBS^#~t#(bT%K*_8{4 zL1euMR{i`U9{WfgD4F?_PCJtvOF;F}ose?kgO1M2R(0!0yUsM?L9R|~>oM2WzzwIT zgi<~2<5~5T$UdH`5&7(yv;KbSOE10T@3`~c0*(h?P(d8Gm0+QTYhIvOpEfDr`|pee z51hKMef%eW!e1+(%~=%l9btI2i+S<8uSthrM#eE`8%p3v$Wqk91LScRvCI4KDbc+a)FRzYFlxA{q?unmCKh^)Z1UW7;_ID zI^3Rm`pLGbbDJL#rk>M0M*qGLk-l?FabnycMh6b$`{=X_mSZ>eeKgBP`cf!UESKx+ z1`vk$2A#eWkeg%*i6-+@ps;BXV0GVI8h5=`W3(P{m3H^DK4o$f6-1p z?aq@qfEdJf>bX0LmmR)TUFY`w=&|H4m9Zbt${#?v{F=%~Ec1fIYLz}??t_AMw20pn z52@@_`HD?p@};&Ow~0Puwxx}o%f~jVn3pavx5I+36$|mr^XC~QJ@*BmJ;^1%M$9(C zguNuZWl$_F~gU*u1no+t&+N{$J zje~`fHH|Vl5ox+tWFil3?3kmSL0Hpd~RL6+OFxu|8M{8ueax(d(Pi2bA-lNcC$$U`c{;L(&^@# zc|sWTf@3_Sq0@FuMyZdFuTJkcw7JnPoIk5N{5QWahqol(>KDP7@NHka);|BQeyRQJ z&;D$?%1@y51x74K7wyT<+vJhT5#gFm_PkNP?0~9Eu@QeVu8(%TE;+gBSTd_Vh@0!K zJk4g=#1vi@w%pO$Jh15tGJpOTf8M_T{qNhvp+g77N8P&~G-5^@?d_kAQhPGlXF<%} ze!d_6=}&#CeeM^2u03%71HO2`M7Z3|xThp}Ey&`UoeG0Dz+N;Miew&k(8j*sK~}sj z?lPq7VuV|%t1YEoxH%bL{M(V@&xE@Ao;hJwD99k7jUu;yzX;ODJ>tS0aqfCW2V*&9 z(GmS+quNKxoK+rHrSn^(B8itpuFJZA9xwIhb}YU23)H^T#Or#&X?d?YU=ZM~bYYYq zvCP}`chqqT=qvs-EtJrD8a`$Fk}50juKRD8NCV8XywAVlS_VGPb9h2OV{J{@@ z&|Z4+6}J&z38?SD1Mb$U6_7~NaV4p%Wo%;1g7?WMpK2fb*vH!OlgIt@VSbd?kU`f2 zA^a#`lFcJb zK0E=#1%X#zdDTyr__xISc(}cN&E+3^?qmI~IekwBlJi$LY)+iyu|r-g$nNW3qu|f3 zR6t$IHs-sJCWju~kd<)zETwOU;$;skS6hLy^?8fQ0gh9CWBiTR-*hbCVeHKKx!q2m zKJAOg#9{JzSue?j`d4}##`4lpw9;Gj-BH{Vzt!w!dl_YCka2r2=hc4Rhg7AO9_UGM z?31p(IbhN=Vw6jZLR%9l$*i8>vI8q!jN=$yY7jXeH6r#8Ku@wyGS^8^x^-MGSZa^4a3pk58}x2 zPJxeV0hCMH)Bdb3+#(&^n_$X*Y!%BKg|ftcC|K zI{Y-aM#4uF$?|Q=BdY}V-Dy%jPt-=xLE#^$B-L3X7C)*!9u%}U3+kps0iNopBSa`( z?;(|*Q64h9Iuuy#gkoO9yxr%~k5oJ`?-(y(;zbr-a((mT5rh1XfYiOm)9taW*Ix7_ z+wHn0cc1^o&$rKh z_Gj8P9*t&Fj9%O11vbz>YB`1o>+jXsOSxFfWO&qh!faACu9cdXu$nwT;p} zsXcKBFKIa`k+dMcWlP`WH-%XYfBQS%@%Q%*ZXQ-??-M}%Au&aV+CXKfr{2CprbX}J z!-xFRpkMg;&$WjhdRSrE?>ol6dnSjbF2z`8=@5J}#RepqbZA7euOhmib$eloj^!sT z>|EtzNdNTR=s^#xL@S zqN5gJ?8NWLP$(mLb8gqs{TtH@uwERr+82eF7#7t2Aw7Bz~3;DrQ9US9a6uSSu``WY5KI{Gqwr_0NzT3(a zDNrKyBuCt=c>+0j^Y}Y^8&$ertfEl$o1TbpY4&q2a@F4M6CVO_C93$CZOs^Hc1pH& zjB~gF#`mr3H`;5jz2>h*a9rnWJc^Z$b-rHl#1oIV!x~q(sK8_REdDrVGB#?ndi4b< zB?P%h!x@kAUPk}0Q9GfHc=tTUsv_3qj~Uf>#Aw5!Z4W*8U={%e3AP^K4(=Lf{Kcoxc19g@ zBjd8(%CAAi^P|9uZhTm_C7Q{i@8U}x138{M*!?e!tv7aQoy?xEvWs|ZmyTPUQw{qx0Hw3ow3s45&OYEu| z-K0@<_ooXhH^(JUkM(iW?#FhHls*O;-M3!vjMLEIZSASMcY;^Y7s2TinFtZ1gw_oH z6x|IEEe)H_Lc=)gvMfU3CC{MilF)iXfY1dm&ca)m2Wrt!KJdn;Zcr#aZs?wwIi?&=4;ht5->7tXB ze$}^UUG7fKpY=h6%z;6sVq5KtWaQ(IOUM<~m|Z}gOmPWHgic#^nbPI5kb>9?(10J> zK~e&rcfzUjlWXgvB zur&n5rVVqO>VAfv?lgJI>T0D5#8>?{3b06-+iOK_ud&TY7hJ6SoYR^HN1T1 z5=D+TcA<;F&noelKa1hVAAj7Bkv{kAbM5Gn!-`if9N;B7xLeG^nNCbB{atfS7WZ!` zn)@?$qB{#gyiUYic_ml?<@?JNtDZOLqlzWP((gyQsq+xav2TEiQBdtbTf#?;*eNYP zW*ziL%E_}~Q+W<_DB^`ZKI+&mzeTG!*-zprg8L7=`ZF(lt_0~G2TF;9N4V-9ePt)N10=wKf)c*b+oB1Dr-yaB2v=k>yUJ0hO^s z95?z;>6H1?8a}FO`)Ar)@4V%_!>&HUvBKToCp9h-Wt}x8DLHgj9jGHo z@u$9Mk3IW<4QxUZU-bp|aXX-0XHTZfgkk^ATzIhPGAKHg2r#3qc~SZ$f`a6 zC(Af39q>N+z|j)Di;m$=a0fvIY5f3_vvis&BEVB-h8s3CI`!P)=)k=L70l~|vorR} zOFFieJMgMsYiL5rm7kTKI7gW^I&xwG36y+&Wh zJ#v}66*5>*BEA{LvR3Rtd~2j>?0z?EuO~0bR?q?yp3brB_k)={^j| zguPDuvZ90k-M8LuXV0E(_xSs@p)v7$_>qU(z4xBX0!x3ni^e3j$4{wxM8=b7Ty|Ci zyat!`2*2w`%p8xwPn_aJ!Op=felvF8a|N8gv=8-7IlN4W7|Z|Q_kUNDfO9(GAC-S7 zyxF!n5oyAC>B5Ef8^7_J?b+u(?(Y|~_~*0)oAsiv2g!F2RJmz_(Jf7Vp@Lca5w62} zR3Bs#4Df4O;Hi#>4{o+M-+H5c`O9DS#O}c6K@ak9;}btI^fN#G+4eI(_j97rKD;5e z$4;r3Uh>EN3Ys={@RaYnAbmW##`FTD!YWsa@OY>GAdJU~8qO00?YXOe>Eh+~t#5z3 zedQ}(X%{bE@*TA!S`gDhvo0z8#4MBVUMf01~1)eUPVnK)Nc8Mi-T9|yZ(4kTHZZmc<4hpLm|eRu)@v zsApYD%AYzSq;|H+bqe|wC4Bc2USh)&7V$UIh+9hf=v%x$z;$I@VbQz6+spU6eb1ji z-(G(8mG;K#ueXaA&byooHg-#HUcG*eHB_gieY}9_{fSB3jji~3|NW=hr$7D4_P~P= zXyKcMcsx@3k+4&I^muaI*l+U0zAi9)c$oU$kBF%mTo2kw302ButH%!e@H$RT!xy?2 zeX8q*`W(NZ{==7E_605f#2q|h<%yrehmW@Bo_p49&DdIcIe&9!lvC4wVkJWnBYyO$ zZpgtNLHP*r3guS%zY?xwQ3bcpvMymqJA%uIPC3o^5j`4Fl&77Q*D=P@iazG=^D2Lj z;zGPQzPU?&_0r|`n)>B7WvJDjcI5{T}M0kHm{QLopSXf}Ra;GQI%V zd3$kZxAML(1@V#ma(geM`kw2HeCNrI&o0>gScmofS9yyMa&9XUz204~=cv$?=Z|!m zjM~Jm;Dw&$T*z|Ma@FL%fRFJgH6Kyyqo{%8bYZn4_DVLoyNM3`fKc%wiREr;@^e8b zN~ZEzt_uyYrX&sWOS+b^Mo;PiE&bYYDm7+}-mHHnVn^gguBIMybA-+GOzNvJ|^$9gO6>lBYu)7d2JS_9JyM^ zl?;V+=Q{9RIN1yzspLU?t3kQ)l=p$pny|$l{~$&Wyq-k+U@6_j%T9!9A9fanwm={w zBn~sGe1O^4(AT1d(-CEFw5yyP-_~O4RZZmh-a{s>(x8doh87`DKKX>|sR3CuBI|*~ z;@uDJ91kWazB?qE>bbZGh8TX@2mfyQj*t~~STI%emCBT1vnJhXXX<8yDeL}L`!ZSO z(bt1oFuwZIOIkpF$&WwR6;AF3qle#+{##WRfnVa`J_K(-+VJR9TpG*re*mB<}FRL+!1%-faKvzx|}T6AeEt_)hnkNN59(2q{(v;-`E@?-fUpt&(zOQIW!G7d3A?Gv zuajT&i9_3Whg5&$H#YeBn2mPk%$fGJuYRq4>pS1^cYj$RL-*Uk#aI5Z_`HnJ z|F&Y4N2RyDAo=)De7t?;Gyk$Z^w5LqA4k35*ybm-ZuHi5AQ>BS(Zuaaf#QxXfA9Jr z-@A@Yo2G6YA8y|?gs(uWK{=M@Loz>I;;ShTp=_1$W9mCgBK+ezhHT`SSu*e;FpM-8xb? zY^e=3cJMpEJm$=IEcuC}x88osPjK*r3@>z}?_oDDX3?@m{a|~G_Z9HdbDZ&1?y)hy zcZ>cX8D0uL}2klRO?rYmVaPcM{(H`*&{jL>t=U*FTl>T#o{Q)?sw40;TlD5N2 z$mdifo~whp&5^NiDf63r}3sKAekL*zvpT#G7L`7aKGy19=wt?+&+{qVL^5YE*pFpcoT;%qg}<0 z3vSehDp7~@=hj|(<<)lW+I7itTtVkT>5cZ-qmTN%AAT2z`l2nC9U-asFwwiMUf4lf zVJnL@pNq|(V<|}g%|;np<<}okKI`~*D15+JTRQ~4Rh~OMsfX&3hb_aVazI1!VHu8ellCCBB zc`_6`vwy?~Uid;AW|13k@a} zp2#`Qx7x{*_qGQgc*u9id`-rnUZ43L=TkRv5w>;3x8cnu9%0n^H6u{ zXgakhp3=*f$9ty5ign-Px3K=%|M}nTyZ`tP?bz{SZDZf2{K~Potx4v4XWwrh|JZZw zH-GcD+Lde9q$zRZM8|`+`HrM?VV|@n&ZxHu!Tyqf(0#1-sP)-`w12Z@=|c`{EbB*e+bk%bz6WzZ*9+Vb)~klb`%#`}{BdqR4#j?S|^0_ELZJ zU9JTz_rt_<^yk9^I(LYJK^fcZQ@Xm^Uwe;JH;D+pU(MT(_qU5$fPCj4zSI8vFaF9G zGI(?vI=smimO2T8C%oCL4 zM_|u=4LjQ9v1P%F+(-}`7fu(cdN#>$bop@0c9%~Yb?oC`*>YWEk3+q?8eY+e^Avl5 zF~Lk$FxPj21t|kWne><+QFQquUHJ+Jxr|x9_|w}46YTO`YNZ`3HZtV#CH3!4!e%gr zvFO^kXTy&qpE-M`z4*cl{*CJ^SMqlHdKn*Lo0|uL%_(yEL03&jI= z^+tSIRFH6ux&Za1Y_1PF85_BM0?IB)((+$<-|;0@O6NS>`-XXx z_W4TVkK*$7TkrU-Ui!yt{Bxj@En?#xGLfzKrrH%X#KLUL$@18jpPEl{p z-Jyfb^CIg<`PE;`&OWuFe=4u@jdC-PXR8?Ze0Mx^21x!iR_oF02~7#C*yCbx{YL&E z?YrpHBoeQaS%XE{;-&p(4Xb?)6fYS2P67GSG3&}jPymg-U1b5ojCtIxyKf$Qw2@Xj zFka`dQvA>(Ub4g(%H2iqDwbZ1wGyB0Q&blL(b?nvw=0PWbcagSk!5kAaZ*^23 zG$ELNM{qq!MAo`WkIQDAi*~TB16WDeLY{d=)rPMy%ohki4Z!Ac2MreG3&Q}=vEbtX z=-6DipwK5F@Iy--Bs;~i^h7rM&Sx97t!uOJ&h1ycg`wOBwbI&^FSTEflI`+F@v=u> zx2q(Ryq8~kNdv)6e=jxthe^s!->Eou{CL~GnMs^&GGKeLLOf8zCmUtbY?DP>k7|Ep z{HTx8R&5%YF6)y6Tk@$pdFKXMP6+rEKHkQ9>HN9&2Y>MUngDFK!$*!wm13qk^ShdS zw{}|-(_jDf-)yI!c*1uI-J5JqI{Ku7EA32#xzp;41byPbq|}ydul&>IWYPN8Y1Llo z8~7e6+9D;U>O(bgRa94H4;?(z-gx7U_ND*vB|jE?ATGPW#z991CQ%|-ho_xIBcj7+#LBH|i(mZNzhqRMUx`*okV8kX_SHuZ@Lf3zt zY!`~>z7UXRqb)|HeXO2?PjH%~5?Jw-aAOd1jfiILfj-A)BKraxD=7JP53DG@f79g+{ZCzd>y*A`X)v=MQ`F-&# z-)SS_Q+HPU^FRd%^1;Wx&1B&YjXm|O3lALI6!C^<#*(w=&b8Nd+`aVD%YIusZARVc zgB}OSOQ(-h^*zQ9zEg}D%JGXjG2U$JI6b&|s6F|_3!&cFuNXZH;fn8M+DnYT)W+}WEb`ThL z7hd?G--p1(0e4B*Zr<=Cj}JZkaC`Wnha5}VgarqBh@@Irdeg?J9goQ=u=WSK9T?E* z1qY#c%7609v^`+5EsSVy*3Avd;#7OZos}3N>}lg&JPH;$6n;Soq^wR zA+e*pcqjMxAfq}-jubSHrydtW$pS3LOCNAe_q#GUR^gMp`)F9}!}RbIxAn2Cc@7@X zyNw0^q48J%wnGV^cimH2*&)M5dbGW++=8>oDHiJiAJqy<4~VYh=6Gf+`^)(PexWz* z*N=j}5hLw7&115}a~yuoB;7wppoMnQPQFBqk5~v~1f@xKgMGI~7x2+-@%U7F*jIX% zboKSe)#J18zt`S<_dPH4GN^D@<5uH0Dj$9Hu}CtIQ%9Y2xiWoYdrJ#6om8!|^!L8+ zItav}_ia}&&Y3;!0#oXqHtKQ(3fO5&8x>4RQt7C~4t&}~*uVdP7WY4FfAS}P>_>^o z=S5hNxp?VPJ9_wN`@$E#&<-BvrAc{25e85Gr7z#_%-vP$nhALMy$JVtg0ZG-E$lST zMu5RO^-UXAeJSNm(>q%5eesK5YM10UZ#{(_T)BLyoqp_e`@(_F@kTo23bjKpBnaR)$Fea-^k)eZIo`?1ag8lr1k2VwElw$8F5`s(Jn++{ zToq{%zwdnOFGDp9JV8JmSZrPM-CmxK;bIHN7JZf9B=;R=A?yPXju3kPOu_;iep4O@AdtoJbM#&Ns2kJL#V5HYK{f zLGK5^+(xrrj^(VH1o`M=zB|ChD&7Xay?wL2su=Nfkh{N2wO8kV_~D2B7&PaHLfRKS z>|-ys)6XdL=5msg#=e2xPLt1_*ZYwVR2e9G^_8J41Sg9+YMIdMAEr_FE*NxAFs;(s zC@;PRehT|ew7F=h9887Kw9#JTORSQ&T<0NnbGwJeXEzXaNts5Qr5yedCBG9W8_TPI zOP_W&Zyll(!S>jt-%*~l*_Hrt*6&oW1G&;)y7}_}%^uxmt^Nlfly7CwOqTSdNuAxN zTK(k)PSvSRPd!Y1n6WYhkx*LJ$`_LG_O{?(`={=HCwK+JcY=H1ykCt|QHpB;1bOHn zv%Zl#C)`E!PP4#Q^0(*h{qIM^g6|}Ir!llAS%wC_1?*S`ExJktFgs=Zn`P>@9potJ zP`Ul;+1W>JR;Ji=9iF`Q10{JIaNasiOfHF`tO~6Y+G?A{cF!1-GGo>_GR-`=vnaoc z`YDV6AAkt<3th7nz(j(0GRfW0K*Ge2N6xsb0UrYj6S@2DJEaroDW5pH)yIo>Lwqn?x1B+^ z%LN8ldmXTE1+y%RyLaDvxBc$#{;qxHsy@YhPw~^A`m|s6MH^k$BpU_&eyTS1i~Vub z8K6dr1Uiwxb(9Fek_&WWc~KHzTLk5 z&2O}e=PyX#O||=`7A~7M;Ynh(9sSC_Xp=&_rUZ57f(PwS-)7Ns&gxksf@Htt{YJ$Y@6$bijl??VAO8`aJF+HHIR`GgP($3_WJp za-U~&V7eZCFk#-;`;^LS5o}HAVlG2{Jivc=x{r=gV&!U>S8>O-XkK)(XADst(r2iT z7;Q*ey9_k+rT~cM9lT~vzUYEu=@bhW$*Mj?94`T%m99q=DRtK5(&bi49rWkEpd*6? zEss0n_n9;A`?tm4dQ02e@95aND$cx|EsIc@*Fu+zFFbBQkR;ryqYz=f--cz1qZP{1Yv zX@^*jkVsraiFfAKN(UjoA-wQ9isMyhl z`*aLm^}_err=MvX8W(SJp_1Ecfbil6_N^Sf_%_!g<17}sr7ju=V%d$6j+1I2Puop( z8hF{ivtL*d-?#v5<8bLYtfUnexM4KGsvvx1!Er# zVlU*R3w@*zicY>Cz!OL>$^o~Vlrr8T21nj))5jsvC}Ui)TH@W?N5hCdA&ODQ4&zGV zCXzlll^I?B?oTAGqA!B$D)u;N2tBq5>JYmrKQZ(@N$n?A=v5ZJYE)z5EkerD!10BS z-~n$9Z_+023hP)H^hdom*r|)Wq^o?9SNm=kdJWd5_Ox>llCl`$kz*s%8HAFmM0gib zI!by%5ltm_B%w`OXE=`VQO2gaF2ptm7k$AKzU2YMyk_oDxz&v{fxcuCA4_F>LfYR0 z>@-ORXTH{JmN)ZkEdxX z{$rn$1Tn&o*qx7^*mQrH_=+d~B{u0(p~E{^nP@5B+Cuj&FYv$g#V@rpXW!F8_?XIM z-@c0H+V!?|{d)WL-};UA=wpxj5n0;KHfS?x_gye8%;bgtR?v0Xr#fDGJ60Wbh57R6 zHA`0}*<~i(D6z<0rTw0;|H&W!aeL#<*ERXcME$q_!*92zo_;p|OBZ5`b`zHw7$H9J zu#sL5SI6S|P-codX_YN^^%Zov36>{M2Z}Hx?&NR*#dmAWo@EbbEZE@WT;)4(67XV7 zdF~3cK)HPRa(n;1_u5y#_SN?NAO1j1aH}0Ubl5+exMW=zXy3b3O30f;Q=7JW72E)xW2Bmu}P1D_(q4 zp8mnY*L_wx&Ye5k-hA_|cIN#v?ajB|>c5w+V@W(5PxL|B6n_6S5_Yxm=3Qu|r$FD` zR(}DHJo1Qtr~3X=r@T<(4b$7#)tBs&WL!1c06)uTPt~BhnV@pPfyiQu5~#ElxtpCv zIdor8>FIwiSdP&IyGXyNHXZ=~R0SobarBno#?9mD+(m!jf&1H|k3QlBasB)e->ddJ z0@Qb`LaON5e8=5wW{rxOkE!IAL0BgjDkJ0w0d5iP$-_t;T`;mM9Ukj)I#?TzJ%Eca zHaX}*IsKF;RnDF{r}M%)3wAjdaUqAVc(5l=WZculmiCD%6TAWX(ugX9t~Tp!vI1h- z?PmkUNS^i{%l3c-aNgemQoq^Oa()53=r8lDfPc9_y~BEFgH@qf7kt`v9zG)nX;p3= z%-vREbhc{Kp4}6cbuD4C3$(ZHvc-NhRJukVU0UrnXi8 z_V=vS4?RwjmMR`|Mg`+ zmU)Tk?BfIp=1xi}P~Q5w((cPTf6MMpbupbIMEl~MK?dEWKPQ-Ar1gW?ZBcaWk)|)y zKm%=JnX#5Qs9P;sh4u5n77;98&i2en)Vvw--X=P40z(8vTpxn*}Vc@bSkCYr3;s>^VI$KwYN3l z{qi4u(F=L*5V~CylWk30FJHOr@9O=VU;VePgeSi&X5B2Z9i z&>0tKYcSOZjsjCiuJB?Ujci8GqANOC4SmBYthE)b}||8O!{ro8KQfjDI^6p*&d zZ5m@o9N$5zN2z4zXG?JX^O-+T8xwbypr(6NLaembT=nDNcpq>~Fzz~Ax32FfXt z@BG9OfA^iduRZe6Bkhq#ANE_vIR|6cFIu~qpD%L_xfsE}s$G3A-^ZrbR!_3|Cvx}S zYWv-eU5;Y{83P{(yz<^5T~Jx?Lq9H*>8aTTXwKW$^g9=K9z?32<~X1)b(;DW-__=4 zkjU~FG{{|b`ax5ya}kZZqV6VLd7jQlf5!+DVat%gz(VYT$ycM4(H4tXSI>frO3}bL zvKASv>PX$#{HQl633%RSX4OD0UAcO-z46+cz98pg(Dr0UdA=rd;=cP7o9p5hKSjRq zhPX3HF95rRs&nkE#sFUE=vn6d(U5U&7d@l@mEN&V1x3Lu(LHhQDzglD*ZD>Lq0{GX z<9i3a(E7UXx0hJLRNwM{)-cu2>ccbpG|DWZyE5%p0dY-1XXexPO34J$V}2Q<-Z_>t z26_57>Xo!vZA8z>ZZpHGMi29>O6Q#bLw0jn=@ate1|pBtQAL2Fqp6lNb*s zSVWxcXBYoFUHj>P1Oq$p)m)#D5l?sLxo~3Ffg)4&K>L(0!OR+~b!h z`7N9K_iK)Dt8J(beBbTmmtXeJ?=Xpk8(sW8tV!PS<0o`N)ugWLcZ;A_6Aezz{FD$= zWw#UPgH`NOH|ofvgw(NoE5EdvR&?ciQCbuXyzk;G8XV{%#T>56Uy8AEgpwpz#^?Dw97>-d`RCW?e?;-&3DY`ACO>SUl+d2#^yG$ zy8e+JM;|L6M78ss5AN!5@#D2uU-hGu^lJ*~6SQO98FV|LM|ONsNEs&FEb#dGFVlJB zto=}4MtFLFi79WWK7Q|scJk!OcKXrN?NgupWZU#xt0PyBSoK!?7$jDHG}enJ+0-A8|8ji#QBui4%_6r;q8CNVr+x~) z7vxZsmag~|+xB6Sp}Z&6&nZGbb@3uc1ZeRW#`JBFw{<+cuSM@W@4VICc;hWEfcbrJZ2GP+eMS6!%eO#3Lp&Eqs6$?S z=bzznN|A6|;yZa3Vh7uOJQeWpgMQrf=+Wc-Vo86ufGZ?jI8q{ zour>9Z5WdoYaF|}Frx9<7X=Uo?CgfxlXgutIu^u69sB#0jO8wpxeeByMBXI(%v{c&SI=OIYSls#(o_x$eujSTY3dATg^3uksuQ^nNI$tbR<`s=^yc{uoDKWTt zb30G0Jp8cwlmvPo^R= z@+mK`NQN4keVvM3IGY&zVx(Npi6`wDK8{1x)dP4}Ak=t0#w?m*cSh;YN9;Nw0=%UM z4z}1`=r`~}TLHA$+N8T+ITG}Z@P@m1Y7Z4ZwD*5_gG$%F=&P9H8eUhi+nC)-9}Jdt zk)Ifa=n8-8P`%C;`Z*MT;TfgLkw=t62>WH$yds2#j_#8M=n48mPT8mLz8Gr-(~Gej znJKarat@vmqCs}Rkx1U88csru&KrRDc z&l^g6aO_!IVT-S(n7!!iq(c)Oi`p)HvriEtj-go(N;*rqvktQ?O!GmW7t>%XdRZvu zL@EXke7VbY?b?<0nidT9s?V&bZ~0{-n+G;LftHc(s|=_(kCT!RYd!>w z&qy2ejCm?k?Sr4{35pGQwtYv=iOpVu>0p7Pte}_2E5zjY2;Th`423TX$I& zTy-d##vgnllIBtA1KQ{VZ)!3058wT+AC=~N)bte=#Qxr;#}(=DLXkL18-1F7Op-sJ zY-Jn$0=%@>buGAZm$0?tCyx6kaGrkVsrHB_phpfLX(zNu_V38*SmG|LAEDMZA!;!q zKT{8oQ$1~b(%7vDs&4Ft3 ziUQA)UKV7y;e|AM*_&5oJw||-nXUj%;{?jB3Pr^?!;2u-QB>+R~btL^;d3+=KN0~gL-XfM9M0@J#XS4{u*ZqL;F+XuczeB~Wi*QqoDMrLJO`8II zQdn$5i)a?!)N6(qQ9^UWi=2>S99U73MxA${%`pQum!z9G(I7)XcnhP<&KL?Mz+d_( z!YL~o$rV5K5M9b`)5fZd7(y3~f3rm|Z4r(v{QVpCmQ7n0+zP0*rW^;p2&FhyWU*Gq z2RU2sE_Bz>(mz0SbxHrZj5>4*|Mt^9v30mEUHPsUd8jjOC#yZAsPJ*De_!N#`)yy~ z$uSeq2M-@U*q(Ue3FVM2+uHP>yUMrxJ#{OhXs9r|8FO46D_hA$9n!g&O&*TD0Qu|+**BBKucBBlq+~fuc-U&1M&3--Lp?vC&Sm%AN^du-}9G#>cQ z={s+~+1`2YeSc358%!8k1aSB9k;fj@q;k`5TK3pxACOhXx|E;lTYi;YHfU9jkCk2n zbX$e?8kjN(!A7sU%ZVFI40y4}!0N}wpzEI|;LgpvZ@<;P^u_<~J9zwL$u%u**$!xe zeB{t(d+sMb-k$sTCtNqyHECa2m6`eFO5LWCo>Yr>`uT$iy>H{9a&udO<+>}5WX<1s z%nvp7UB+DBWMQ9V(dlCJ!B~@Q zh@?B_c=a;sQ{~t|kM{aEi-cXj3@YpiJ$G%HY*QXt9-HU!W`3{tJ&jQ>zw)ZT(s1d@ zCEtnV;t?_%S|sy?M=tcC7Wve<(z)m&W1MEmlNM+Lbn$3B{QNB0>C>m%V?17Z;+S8O z#steey)S?ofAT5V4DCogd!?pQVqW>8!NV4xNuxS`aV{WDgHrB>T>^S$`R8E}D6i?4<y|ZUDj=iH$ayg1p z&eONr{>=@4RfC^?%UH5c;|dqN(-zmSZ)?2U=L)g^g!hQ5M9Cg}WXV@q|PqNemAMk!gv19ttT?#uBZHoi)7(b338${&Od$k?a(V&Sp+MQz>io*19!qp>!z#BNb8YsHnK^QSddt&m(pdL z052H%cknBnX^Gx>=dyIZ0;E~pqHM*nbS~(hg%(gel$88BzEy|^_O&Opoys`Pa8QIE zE1X1>?gvf;**Nrapcdy!9vS`R5w{%l)MYge>}!&hL29b&TGRkC*uqkuI7MxI~H$fPk#rM(WguR)XLvJ=M3CeVRE5K zRS)OK6TW%jsXFX{p+C3}keF<+*M@4-=QtBXzEAu7H^14w^X+eGQG7^qc4B_hKRI;# z=rP6Ph8Dul`TNh;x0v9@)^g1AJ-*n&bb2A#_`?>7F&Kag54|0RlW-*1mg|l@nr8cm zBm}E|6

?!#*!wZ){!l&%YczbXX+rjH0nGIxyK6MuF&Vi{yL3 z0?t25Jo|-XX=d&x{N^7F7$9~apEDxs_#o?YB*>veeO$3v)KS3SvR$Zpud7ck;@}(G{*A6xF}7`d zr9Ip>$g59?Mw?g%bX-y#)m_vsb?G&O1O*_M604csTI9);*y zp7{Imd}7#%*REdmW6+FG?&Bg8Uw+2zp@$h$PWg^6KC3wdbmn;AxI#-V4z2gOYBhu0 zBIU;hV&KN;plwu_ip?URbzUcX%?9!cte->}qL$cIUtdM~hsv}s)!r)seZ{qbFFxG~ zy0S8`8>T)sSqq#^+t(OUv>d7F@9{hRCUeLcrOhl8$g!1fxYRZdophQCAczOO*rJ5- z*s|+@{4$l#f|d=g=Ft8f>$v;4!w+Y zmc^oVG(dxl#v5yp$$q z-=VWFEaz9C@(3rpE8u~75u;hVwPbU(Zp1)7dogPP)8>82mQ2qxFj-H@6`+eJV@NNm z^2jDOqI`|q8cTMD+)udE%aOP^UCV>4VB-}0IZJaTw4^5aD zL>_}KmF65Jkh@H&*IM=1J^QK|VDZ@5*(bBpr1(yUq7T7i z5qP^UY{5fcv;lv@U5GEJK;UStB5?|PYd_jJmlBcE`hhy=A|35Snb#zGU=l%Qg2t4BylXriIl!=1W;kU0uD^0yTsV5^)brIZ8 zaKc?(@bRYl^ZjRE$yOG*!$%IaW5XNP&a^&x(rn!bsmytpmL zvsy)cHIv-H=20r$PAXk(Hy2`83m-XUJ;XL$G7fSPjQT(-CFmecUyvLzG_OpN7c`rJKwG;{`{6V7jLq#%Ho`_ zWz+>3U&ZfZR<$D+yy&rR8~N?)7+gJY9jQku%O7n}@w~Bp(=SfD_r&q`)YDJ5haP&k z-FNbYFP3rlnHOnEME|ro_3L%S2a>eE|ks||Er6GX??Ne{70eW-2h zLydmwV%AavZ%;#?&riuy7=2D!1LPb<>1(keA6!xhS71-HC))HS6!pFSx43wtHsOw= zjliirDSn2JH`#MHpO|wI(&G3^xiUmbp4b;`t-_p1It|wG-63kMnN*c-kwjY@i{`j~ zaNEd7c3O}u=_*>zVf-A@>+Ssci#`_YjeO#w^wFb7+GD35GaodEPO>=`1o}HVI1ar* zthQc8`A}ur!zZD+f6R!g&=<;UA7gipZgbl20p&ws&L<{5->uPA6nng6Z&~L~Sg89R zF!6VLx09bdSi?8@CwfZAFY8*i(f77L_U930bzNCtot%u!TKw!~PoGHQ-lEUN2Z%5I zAHL*_QoLgVU_RL~=#1cS70qHwFZmF^7*t?j%CaawEppk}M%gc0 z?2~3fg%34unTi4ZtD2thpFMM?z4O*PG0Xr-opmBTuzA2QgUQuo>EVPb1^$iI1Kec; z_%EX4GeR;LGnvGc=}^A>)-G{k;D)YkMPElRgPSCGt+Rm2n}@l}2A%JL;@fw=^?ZBz zl~>xK!&+z@IN0{fZ@vfk#_MlrlD5%)```b2f0vWRP{k45o=+>`J9DCJZgM9@|FF<} zN+&L0*;h2A^&Bvz(uZiPnVXVzSU!%I^D|iN?{DwE^LG31|NXydqR-v0+|_*G!3Wwe z{n9VB2kt+mMZOjolD~BEvfGXC;8uU8fB0^nyJ2F<p2ZP#$~TRxN@H(;HAHsMNe9Z*d>f+HyCKyN6j^@z^xK!F=Ju z`Syb!{!okJm;A^rKcPb%c}ikaeT5bzHV&y57-qCsh`9qKF$|qdaR&Jmb*9G z+dQVuT{Ow5F1|3cx#>svd2|}N(@&mO`lQQPsPO_WWVnNz1t53cce}_&F$O5eSjydhYc#D1pO)gK+-`;rZEnn#1n4k;tMr|(q_yQad56XFJ zC4s&jQlIkZM?y91q-xaN)3|A0m*aY;K*y-3@{1rGT&(d$YQ^`37hiOquW``t({{Jo zlR77F`r>rj$j78Q1^t3pyKeSdG}nhTw%M}uirwumgT7GuW54`h zoVGt!$Oq#d>B4;Muk%r(tv-p`NJme32x1o+f96CFc6%Ag#hXfnMO`j+KaU=(P%7h} zQX=9bi(u$|NU`r63mL6cVnJ;l=ezf!)o=*k(|3O&X$4sXPmLF(Gm#37v>)@CcnEJb zE<5pa2I%}#r&`kMJTMI#F+B}Z18?bYXD&?oC|ja~;_ZBOKosku_>#P{1FbOV>VhJ% zhn#fn7ZKiF(RH&ow{6V(bvh%mPA{~gFAsK1FwocORzmy1p8+Gb(9a|^>1AYaaH8u< zzBqH8s?d2|%GUD}GrWV(shE?lpYz$p$M`$PgniOHZprsOy}0oN6F%u@(kUJ2V{!2Q zyYIDk-aq3Lu$4=mJ5VQ1obYdAqMMU2U484?Ry)iiot}gd7x{p(DQ=+G0XOV3dwpQr zF{NLN-|+-VG!bDek^WbLt?sxv7{rOk^yd7Y{r1m3>*REdEV(Mu7#n1m@d-j=U z{2QiQ+)>0gUNXUd>6AY1*l;t)FH%u{o^*E*VEuDiv0>_~zLfD>SBNNt)cP4guC!CEiIw1CwxRKbACEhU=Kj>T5tE?xFic1~3J`Pk^-ycT(`|rQs zUVi!2_S$Q&`{#8oXhF>5xxUMFfX8`xxfaI|V?eht`H^GE{)>kGx(fk|tEG({;{e`y z5h0$mB2QOrd7+F9{fy)Gh!(yZo3gEbd-(8CEtWUE7(R03uoun;Slk`hr#^5{+hJee z;HBgE2Y(iex9mR)L3%c2ZU@<#_VT;^YH+#*ORp>4FwASFc_c&#iXl+BNqd z>dJ+q>smlw)xwuMtXHpIZI>=zv@V(odmFNmJ|e5!eO4Y|*TWop(a^`nlNxob*jLAp zzDBuX>iSWG#0j4ml!*6qp+Ux3G#om5s6F-6)9ry%r`ltWKGF^yIpQZ<;9+r5iwGqH z^vma-vA=cx#f&U_AF=MK-n!nz@7M#*s!m8L8>|1 zNV#Hki;GE&C5$2Wcs$~F(Rtw;-+A1x?cs+WY{zv@<|1v6QU}L!+9m$=_SMECzT<*} zv5}N(Y+qOzzdt%J7-fZ>?L!;n7Eom=_ZYK- zPSQ25SAMiddX(J@%eI(^(ZksTQ7 zS}q6GuK?V0zb-#gJ_#%VnXYiGlYH=ZcjcEx6{k&x-u?0gXC?TtLjD~AeD9$Ck)pp- zCK;V87_Y3`a(O}$v1cB*y9i#!!kyr$vkDV&2UG_g50ISz@5D!AblM`+vD8X6Sr}o~ z63?!~ntD>{6`ji%6bXy<9dro`KJS2udk?(pfQ;{0lJ@6%3~qMJzTR0oz?V2Xvlh_T z>lz0d%;k|mxJQ1{Y&AFpPBSP8aq5brL~VI8eDwYt+Fd0An*rQrdooL%SNwaXIet!JTUXMPI2cZDlKqS9$a^FMf1$5@* zQf-wcD1GYzuRYKQQrvOFUu5w;|LDBY{`PBMYv23F?`cxc-MIX`4#(5Q3m4kI`Pcud z{oK!fu3f%z)sL{I3&a;Ct;3047l&B0kX#Ufmxa_&QTkDz_;kF5L zNqf%ah0V>4_Wkewp#7i!^T)oU?K{C{yXD8$Ifj1bXMU!A@>8EOKMMsf9_Z>e9V3W1 zFMj&OYzd;62MTbERAe7rG}d?S->C=kLHa1E)F>d9N#!KQ$&J$9A4DUZQ+rRobPW>r z!X7`l2p~S{?K_(2i>iFc7ymSka=fsI3zWQMX=7v4cXzk7K)S|vQ_q~y@$kd;>Z`B& z(cMcIwb0{)EWJG1$)oiwBJCr(>38J1T^4ODzFl9e>EHe+VgG2S3ZC|MQEAGiO*)x$ zakRq9hxOYK|CvyeiXBzo_2;V&e4m)UAQ{m%R7Y4C2e#A)_#M^wk6JGN5Gxjhx$uz% zqT(tV3u0cpW*0=@+lEsQk+J%U0mnNR4XP*?42n;id_gNoJ}C3=xw>-M_4RgeUBVD)Q)PQ`^4!d+9Rh=x1&c7`{h=E$3rD>h1cJ&RGwL-N~N$ zvooe(b{(RVn%s82&~00X+R%9z*-}>hlSQ;&5@=e*O;Osv;R_*ey!nR4)r+~HfxIT! zv=NV-Kl#+-S@Z%4UcJiGI|tnl?4=K;4%*uuvQ=GnM)~)_QMN|h-tHnweyGQUYTrea z-~3^ZSZ!?F(=KYvdE>R$UC#Ri=*xVaB9nh)7TaY4?bjE!27LYakIYyn@Bf>IVr;UbLE(^AUBO*;5ytlPDKBWf*4Y zN1S}k*^5z1dnZY0vp~*EckcwRVr3D$YlmIJ+(4_?vo2WNEK}l+F&%LJxQz~XoHaZP zbh?ha(h7Va3U?Bx2}`!u#b|BZmgIKC3LohuU3E}GhSxH6fG_jTh+jP;cw%BzIj!vt z#kq&Nn0FmNZ6n)uopSlbRbVaHoUIoJ>Cbn6;Fs@A?72Gs&f9Nmdq)c^9(9%soQ~Pe z_SEA~wgU$b_=+@xo`)5sQ@)$elp#|nUUcK9hbdv?5v02)u@NNJy#yX~*wdWE{WzI; zBBK)V9NgS&&p-e7?JIx!XTEdF1eXaqi~4tS=(+@c_(uu$*(9Sab~aEKK$7bxxZ&X*$;;w&cqfzxYMp%{+MU zaPGcXj=AF^0*B*K2r}bgwbJrmNq?H)?&GoE6u_KVM}q0Jpz^HVH8ve50Z zGYxL)k0gt!ZQp&SZCGTTI`u$%?6Jq%0}q_?_j^wqJ7%A6$T(kn@SBOzBYnP$BOSB@ zZEm_ZYmWcqdpuIAPaPPEjq-MgbOB%Cn-{^6$N$n%8-PKZi|BZ%=Zu*T7JzrrOIx!i zPuuoNOq{hRB|XxOE78b>3jmKJnxqR$e>i7^H%wI~UeiGI;0rP3XMA3N{f+3cSY#NF z8FwCi^wDl4p4ErNN%A&X#nC~{fCry4jnqIIHnJ~*zAhE`lWqCt|OPI#=b!rtzSIQfb#TR z%R(#O4(MrwV8{dUdnEY%d&<$K$jK5J}e=##YJ@e4rpGaE9>UV-2 zusz0U9q%2;(>Uhb3;$ZZxZY{Ev%98zvJb|xopi0E?`Rj@qU#@)+rb*7#~pSFsNYG4 zPcnuWI*)gJxNJ#q$=`6yI+h2m(w~7QgF|>SKo>7;PWAzbBXL<*~OPudE7@tp}X-)r2z|A5Mfx5*S3 z@rRRh`ody+EyAIists@TjmSe=j0^2;XPkqNmw>S-`>VhD>-N2W{Kt0a@F9Qq)jyx) zrn=R(u3vADYLUR>(f6J_>F>naHEmoCr3LK^G;&t&j6f!Kr+QK3m?J}m@)1?%qNBq~ zwZjnN)D>Fn*oWdNbY9Dv)fMVAeBlIFlSdfTmnh!n9*=G+K!88+&tT_ z53}pzmh8JdwDI%{$=qe{u_}<2DV`%n`C#>2 z7v1=fW2SifxmNHUE6Gqs{N1lqmNCOD9kgw4YZt`loQI;fwEKb+nZf3wU%SIHQy^%& zy~}>INWJY_`Pl2XkTxG}!MI$<4XAo0E=65M>F(JD-5(A{Pj|z7+;^Xq&VJS~AH(#i z;x(!BvC(fR$S~c%>o54s z-Rm&7BYf;c?_)P1APY;evFG`?XYc+_@Cxqe#aI)dSEC9fmsv;oMP10Tsp-0&ly_Q3 zX$0pVrkAdrF#AG=#3-^}ZY2g?V9|#tVz6G|72w0zz}D$X)3J+azK;f@-JM`R zyC10o+vrp3oY?}UR;^nV>XWi#PEhJsf@>3{XHl=wV!!B^y}aFdi%3K{nK{n;GuTV-=F0> z!(09yF^kAY9(lO^_HX}t%kYymRLhHgqGC7kIW!hYUO>Ubm)mgO8S3PSPb6YG_J8!{ zt{m;rX*~|};u$@q6Rqpv0bOmx?>?jX@1K9Zef6*Zni9W_m3Brq&CK`9j%tDY`Okm8 zJ@f3xwD`ZCM_r|ZM;yIKlERvh2C`i3>3w2Q#o6(R3_#D}25|6JPB}`_eaJFE7pGNxs-kAL8e=@XI0Q zi5cpPuiDhL7%J>n`s)DljsZLA>G}$!9J@rtG<1_PzxCCY_CY*mh;Ox7;*@w-zL(ht z3kZ}u!rG~vGKwrmBvQ(MYyj%J1Rq-@X!q`?Wr(@TRL;dW+U&Jg-)I*vT~u5(24z4p zFBchz*~yb>JL;mAax{D%vVET1ac~uA(Wz3m^G^$6K!w=~_yC<_mo!_Cc}KO!&i+zf zdUl4}oMS+&#K}Kr2Bg~g-daBJkoD+5il}YQ0Hr4T@r;o;g3boC#NwA zpf|d*G0xzNl9R^xf`7Jy3jJl=SOjCVd0hx^KgZ}#XK|*WUv$1R%;UW*mR@`FwRVdaYN=ia z4jgKaJ;7U|B~IP!Kl;iJI^q{5W?%cR^Dn{$NsjzGV6sakDt-bB723&*4ILs(hIvHQ zs%bwGiUD`%xI6eK|L1?V?|l2a?cm|Vc{Eyfa~GUN;>GrppZJOPE5Guqeyln_al@Sr zP4-%TI)#^KG5I*Cg>$M9pEx?_35rOb#MlXCa+0ZjCPw*0J5i_JI{K(%qxec@s<+TJ zbYxucLR~yeI1g)q|AX&;uYKjuztS#Wz1j{RIpReF4&KmYhZkm{oJ(o z^`q9jeZppFPmy*^#&J7*#8x!5q3hD&MX&>{3=Gh+Q+Vu6&w+lYP=5y$KbLg9?H<*^ z$GkT69Tr_I6v@*cc}w!SbLX@;KG)8lKi}Sc?~LylU%q;|-PD4Op9R7V^!dUQ7o=o? zV=Z?@Ny|kA#EUyyjeZ=#7krHh=t?MORv~%NnS0-{R23G@Su^Pmt+LIh9Pq^+9PvMX z!AoRf+rQu2+Yy-RygduWc0{4yz+@IaR4NvZRTkPOP8@H?wZJ`o{HPYZ_j%(xq({_$ zdH(4mP%ZKI?clLTbid{J(l z@32Gm@zTr3^hW`7+soPbf<5e0&hem}X^VW&+-qGl>KXawxf`)a{LxCjP zd&Z)L#TygU%U3V8pZesdT~8hbXK_yqScqXGO@^KH34CGEV44d})CNcwt*3p`B?jq3 zhGQUo`YVzXkYU%3dH{IBPkfp9k?l4tLm7ym7uP)>4cH;&iol?v@-gBjDc>pi)GjAp z#er(T#L1H4vZ;F2BG?O0&cNcO{aL8g!q$s!^h+Oi+^=50-Y%TI;1>s-Idet}<+Hw9 z%y*87KQ?R+zvy4q$3Bl_$2N9&3^M+E%+Vh=)m*=Gzu?z)H=7jkGe z`l#ba0WvTu?Y$WyYk%Q1oAx((B$?xhz(B+I=I=D}Mr$s*i`(;dqUGEF7i^G9E(U`2Vb=311fQmFL9H~C`QQ8zZ?wZ*a_~c zKE4I&01Ns;p+lI!9|*llwI_){p`3x=amIepNMeIDn*%+SB~vI`;BgFnMwMkhwQI+u zrPJek+Ap!2;d8)97)pJilLl0fxDbII#=y7Ve#c)i@mt3&&r<{V$A!WzKdS!ZlTWro zYI9y-2GUw-PsY^)n;aj~?JCJD%wU78u;`Mg)nLn5TUPnfb|)Bht@CD8XDIN@sbEME zOD<%HmhMnx)j9-1K@f;F!GsSKt9Q!ql^*vkfw6#Y4LZB|oVEg;*}H1!SV)w!P2;+A z`gETmw-Y2I(N!MwjkKk__{l*vs&XUHInqa&P9N>kA7?CRw<@rxZth=m!Lp7uSf}g* zqBQJaX#soT^~E|d%yH>03|XY?OVc=hKr1?!(@7=vGt%xT^)PCtu`j6K=r}alSw>va zWFj!RXjH~r%J%(mELVG#*XD<^u8n-+*7|1^y_z#glpbvr#6!Xi>_F;v?q=QS1}- z(IWVvyNlpu+;jHg#kpUtL7mKM|NlRrE+0;RsJM8rB0cW^2~dM%+*oX@$(5e*G2z2S zd!;kq;vh$6I1EP}3^>TP+#P~q#f8pSs9Yvpoqq*Y29U^!@q=NoGffsUczDn#Gfwn6 zIw(_tfQ<4}umq+3om25;A*}+RWTls@ZRi&%YHsKM9NPkNn42*9)P3e( zZ*RBfzxnm{&2RpF(+t(Lefth*5=y*pwrf|fxBKru)jt1ApKp&m{7AcgZOeL?^wQsN z`fcDhHPPj69k#K_p7MT2*MLsCJ8GWdXB#p1yQ(jBAY=Lj(lBZBVp_}yI0m&rXVFek zrr2QF;)sNh54h^MCY`#B$2PM|v-d0>BEzv89_5LF(p>alA<7ugTRl8#zi7#$#iaLb z;PXBHsj;msEsQT*Zdb2eYuBz_@f%^egUn<4=P#W1%Z6x2{6ydOb`}(M$JkzJPg~eK z(W?&0;}3lssqou%`!>|oJ}d8V$d*_=NiZ3iY_{1i0`LR{e(-2GabQ7yp=CGm`XuCplBr(IWe+T##q6X1!>WjOYxyQQ_)ail!b=?9@1(tXQ|A~>k)+;%S3 zR#r*dGnM->|0y<*;G+Iz17gpsK0Y?O-t0?jz_IKnYNW##aOhjkS!>tNF9PiM??Au& z(yQ&F_I`Ps?CoQ0z%Pv*e68ex2kviAKmD}jJk)ee_RgyKV7npP)LEqz|FZ;bNBwT+ zW7RQjI74kKvM;piPe+N%efO2Nv3@0$MS6sfL4;k9ev<_c1TM1m)>gh`%QE@Il@#TY zcZaEd17~pyqS5s|9wH;*^p~E6hm28sE9!e_Y()d{c>%LBXZMWm(|VNsMa=y@d+PvG zrAC=$9sT$rsgLM!!GL9%^;q$t=XZzr^;cZWvZGGV5f~CW%M9AQ+!DHtlNc1Z@5+>Zro{P|H(b+16~Qm;C=_k!Jc zZK0QkFB1VuO2%38ct?h-N&V>ZF$AFV-_6Xj?B|mhDxjogr4u>Zq)c2)cG#OgvWtMm z1}Iz3e@LKWQ)RT3^L#?r#5ZvwnUOVr^1Q@QAv!-LlEE@aoRyH6uWBpf39^m!ZL;4- zu@z93tL51WWoM+#i0zcwf6{#iD9fb!9xZw|+Z%7Z-u~Mkeo+hFYwg(aW9{gX!{WKA zMaE4pNUm!^@*jTtKeVTwdB%C}qULT}78Lt@#f0{c5xjH!OzCkjkp%r9-94aW9n zl0>YlELh~9kqNfsEuK0OUnW~T#=EIS|MTDeR{N{3e$9_UA3A)*liZs(c_~p--LCs5 zNec&XIZ%VuV$T2C* zWIMb;j*HZBZa?x^i5`Hi zOx~S#9eJ98d?u&F&E@-4&IKYFcAh(=s=F5&(!oBP3VW6Ey;4r>H``_PL*8J{g^ugm zScF_rJ6_esTfhCi?rklmx38()Zukxxwr}wEw$y(PVvEZ=)fVrah>ndLq8}QyoU}RX-5z7efv$@rC$8x z8cj%)2qznN0(rDKcfRI+O?XJr4-hIkp_%~~+YYdZ%H1CW;!eMtAJ|+iALE8c^*f|qX$F9K9^CL z#c-Gw0_ry6v3t58KOdGSTmsq-dA4`oeYd^+#+&V$`s2oazD^@e;-?CHpfN<|Sf-rXGDg>< z<37|??w7xj7(fi&o=RJ_v+zjP90T2iP^-;r9Ek=%COqkOy7r#F(W=v zUg&b(>a+XU_fDChkJ-6Jq%u9NtttZ6@!ttXo0FYc=X^}uIVLH|yM316F5!eWH+D9+ z#~QoqbgYA=CfSUo$%d9T>&EzGY`_7IHMd!0jCw-J?Vj@Z7Y!h)>B*whL7}|6yGylA zPC#Ts*NDZw@G`w+NoEn4v>Sd25PAaThvs{NZ5t+oR2XcM-e} z^PS+i#~Ib3N35d(#MY44Vjb^VTYbMrwLeyr@5=}Oh@E0obuZa<@!bsz^2l~Qq|sF5 z8I&*CuuPZjM`Zlz0|G~v^4tmXl_ij)l)}E{goiKDz=79!C!{3%v24sQ%Pe86;{u|C zqWIWtnM`~lY7!#`1pZCqjxU2GbyBv(*@M9zbtJcSok!lbeCKgo{7rDoaz`ulZv3`b z<(;(3_PYMzxbsJm{Z4=2@yqXj?|bcwU;45pa{JryqeuN%FnsV|x_Hr#7yr)h{7yT5 z{6xFHb#0E3{`PCKgLPM>Qv-7Jg`OimWG4Tr9f}_yGs-88ZlBu3i%iOdF3ThZ+N3HC zX5J)8@F?n`_V!zEwLkmHpSE}2dCxB$%7R|Snv8Lm;`-IA?P)FeKli!MwUfL(dh5E& zxzOPkjiJbfh@}Nnw+S}b0e#3@4qrOmc}S7>ca61oETK80k3qlN(PFVrzcTC8pKFUu z%A8yPrPf8JY4u#fX3Ms_&7d{$50Pq%U!%Z~o383mPWcejHeSF#CCb+B45Q+wQ;r_l*CylTW8$8&A0K8);2txM5TBI5z5*qP2=J9=+{l(bE$ zY@m1&|0qF+jzy?Rx;(}UrDw+EZ=nf^CY3I zqmnk4L0dHX3Gyy-9^`Y9==%cnW!eV?=LmgTB_Es%A>bR&SgvxcVRtj{2CfxdyF zfsy{fK{!A{GM?b#r|Zh*@@`uvZengxNL@#@g-J?7zOkiPNEM5x+!5mr(}0r40XsAL zFeo?7nB+Q4Iu&Alc3t#xZ{35Nb>s!`MZCTi4fgj3@)Mx5*_5=FN6K_TLew1B=`(hRM`YhMfy0v+t zwvX$<@<~Ztiwjy>D8b{W+c&n_-~P?twr_m%o2G3ZJm@yE9<>wSfo4MXi@*4b?GvB; zM7z12?;A4__5wwU>mmu0I)1N}@BCqB5#8xt|0?diB$)wKM;}VE<=J4Dopf0)K3J2= zvycx@e1Oj0nHiI=IZZaat8m-l13aBpsCI?U<~~4P8TU6;hE`HfGjHhd!B2w!&@*1t zSP`8nHb@uHgS>U$3@>0Z?FF=zRSeRe^ab==te<}JxG%ms2bW>ns8Bh3rW7eaF7_hd zr`NvQB_7LQgNt6yxJ{6%vCk%5PiK|Uu_61uLyV6%DMK%D$P*y+2m5MdTxDAa*w8(L zOc6>)0ebvH?{azSpEyS6g5ouRk>Juk$d=yfr?F9Sjd?y&7wSxW^PNoP?T(qWm5#tE z$Ie;9-}UY~;&-=WO4yd{ZZU_6*NRu8K6IIPXacsL6AZFjH55r)BITjJQ z^cnc0J9PO_vd%Bd&Zz!iTPvtOytDi&;Em1+lP@0>v(BpT2S&*|EIIZjjD9ZpJlb9K zf&HLk4OV>ax>xIh9=7y3_|jk14zw?&>POzgHi;@@M$(;V-IO3#^3D42U6tdgp@m+#nbtFkw2JFPx8Gyg#u}?oHt5FTc<}N7U%=5;;NS%mvMuLr0fMj- z?_LmH<)5q3)u&pb>qKmGrPl>c%rYYQ&QdQT2ED+@!KtN1s&Qv)c*JX{GaXbzVWy1=&=*+@R38-k6rfX z&YW$JKKf|;FaOVfk@$W;e(JkelI3yGKuZE9DNq-DVQ`MFJTBbPX{iKtWAZ=7Ai&4z zML%nydiYV>-v9V%7j;aQC3#G}+AOyAX%cntz`^#y3oo{>{KZ$=g$tMb60Mq0v4HXS zf^~xVsh|3E`{buS*^Zw$?#CSY&J7bZs>k<+$wOxX9RKih#8Q2{Sisd>5TS2WzpT5` zhC7p;?x+F?wLweYOnk#!`jV&L)Ey}>^G$%)q|lKq9U;@Eq_j=_Uuo6FZnB|P8DxB+ z1*a5e+xNv!&UCk|L=MQ-deEJ*xaZt>I|+yEv^iym8+!w32Xti)dZ z!gb?MMJ8jLOh?t-lLh(6LW&oy5e+Q3{e3P|nmi?>Db#UqdE`3HeOLd`3r;D|F=R46 z+9Dcxl$@B!JF*?fk2=Q@qXmkQT7h zo#6fZ{hjpJ-*`h~#6|Ixu8e1> z|6hUoR@EteA)s=!r}nf{r*v*#h`fG%yS@0*OTOU9G3_#qr~Hi6W2aB&81I4- zOp8XpnfnR*N-L#guHVgi=01kLuG2cYuiDZ?(ZdLUo~f-Wv8J7hQmhNG(p=cufn!H3 z*cTT1@*XkAsLL(xVqi2h)Nk2-VLC=9ne1j2vkp<`-2#1g*anF`$gGbG?W*>NKIzE# zGwEe4*C23{^FoTlKJ^a3kQR`Q+Myw$fr$)eF(JK$v-dG7!=*KN8!>93XF z#;(sJ;c+~=kEC<)S9O8p`DsLR90xq@cy|%JiXZJKlByv(Ds?9cdpq7amTZ3@j5>DH zHjsrYi~}8a`Rx~J zYe^j^)7l2^@b*H~#MaCaiIOh3hJCy9fyCPFbH&adN_V>p@xjON6;eM477C345s{Mf z3AGP`EUbBCPO;f9dL(AQ=bs_40&S7&ns8yxXg_6TFn$a`5sL~XJ+WgV*9W>4AP*Bd zCC9e8alpF2^xwbOzW>7?wtG*W@MGL8@@{T#`_aA&7caD*`Rr%fzy3GB(zdifWRZx) zOd{-AcBpn%^|3?Zaz&k?Ab>W-dl8T=GNSXR?<^Mjg%F&i^mjw`_KS*$0si@uaO4gI zS4^3M^9bIVv+uV*{nI~fufP7fAD2F$1wFbsCGwcwmfDV=Tl(0u&uBsXQ*Gnmrfl)O zwbrg{g3O}oplJDRS1|U`b*Qo(`fsn}oG!lTo9n)4r|7<$3e`NJdoib&kS-ei$9ej1 zpY(TCi?9!gd9njjFLP2mUTEaWt2>~nilY34jV#9#RLNw)uRQi4s?5_67||(RlP&8` z(yS`?NqoO#Rkn}c{k>H$C`*0ex6fP<>A!^>)Nv>gck6B4N383^r^v9VuoeuHVmGPjWo*3?RTrqB zSkuDTt8`L{jq<8fxJ$=eW-CrR+dsrFcD|p@W6lV%FuQW`QhQAc;7gY;`4N2AT@K+B zd!7#AP5Vzgak@SDz=K{4)6BsA{v!saDmFX8>qTPF^UEL>)t|>b{8a<;#H6s!ZqAjI z^imdmy#x2r)P0`*bVKQvUwTdFlZ)-ZrVk3!w-mqoPTtoZfBbQer}QE~3%d>V7tqG+ z(@whrzk7WmJ@m5zN&6aI;pH>-1IpZCJ|K`^)*0A*k^`W`$7+)uL0PrWm|jB2Da%ut z>-h@Hed2aN-5%K7A3dH5E4q7_OILZgtag-x$0^B9GJQ|qqpb8)$`|b{l-^|M@kCQn+9T_AEH^Tfw*56-@{~`KeF0U;DLR)1-yp43>7$vEh1n zpd}*;6M6DjFH@>x>=Lu2+3>A<8Cg<&apwAHKXsK9Pe7jU>rr8QqLmAiqbx48IJHmc zvbwn&N$$XYE>hfRfAyDt)xP@=-);Lesr7f$w8d`ot?}Af){?`E%geMwlbX35zs`s@E44u1k;Ah`HU6B~APFq&^aJ+L~S3rgTiA+E0&7 ziRixJzX4P}O0*jpGr4+xPXv)=u>RfCJqx+@yzvD56WGKj*Ju0iesd_7_}bq z>_>j(oK>2I(dT8=%^b+>&w7dW0UqD+=Vk7)S(h;x!qCcc1x zkcJ^=tMFDi`O@do&K|EIr3hjVu1i$zabsUQd*)1g_0`vW@z1}vKJYOPav|*Adr!2} zkDqRbxG*L@>lFNQE$JBJ_v1oEqWLdZ`^z3|E_?dd{XRzq<%t2agQ99Vk`i#u)NbWDE4FFeGm*@eDBg z0mtLrG=vl|ZD>2pMQmj{i790%oY zb}=;h*3t9bl}Qpi=2|p2p#~str1@vB(Sd#G1JRXXh0V||^+%p`wxH7ux*oPhkYA?l z9d=#%vj<9GTs!+pfkp)v^D#3Hh=1;b+UM>U;|@RF!Xv_>x$xx8MA&-)sjDA8O~% zU+`N4nXK>~VeXP1K6D zlYC$e1Fh2DOP;}=3DJH{vOF;oQpcog{$erlJo8NZ*vFpronsctr3JvxMMJ9p01n4P7%YW2a?H?}XwnRDPL$J7D|v812`wTyTDgwurP>aiD5J#~RsX z8_Tdh^Q7Hpe(hIcC74!a#8msvmh_bIE*_I8y#t@N&OJkXGcA2~F)oxAhxW`%#Ko9y zh?LUE;sNjwq4eY)AJEWinZ>>}`8{DSS%noPd55q+9y7@#Kl$O0==J&0gvyid=M`;k zyBZ%Y*J1Y1To&=WSi-*QU&LrPIEVv0iJCfRhZ`Y$@RQm}t^40Huk%BP3=^sKSXb12 zn*Ck!aUGUy%(5NQ>4CQBT_w3tW}BlV2XH1&Lw-m{pE_{&*-+Y(DM%(OFVmH^j^zzD z=^_n^Mivtz{T?3eR2C9fj$Bst5+a*F>{266BFbsc$tLVN1fd|&Ke;;WV$s#H{1{`; z5Bfhc*hK7P!Jy4`!-+acmP1UWn0UhnPvnA{T(PNC+oj8w+dJ>R)82mj?RM_WIq`_7 z;8mQ_4!`3g8ruB5zX?g3-y0Mj9FrgTr-{`~H#%IJbVUIY){6jgOk%J{8F{0Zk>f4} z@bBQFF7BA0?^5y|EgtRr?ce_Gw*SCJyLjQECx%SynC!D4?mQn{&<_~^{ZQsE2^$t-)fIP^{!bJiepT;R^ zur6L=6kn(}r`q^MAF*Pimm8#u4z1FtMFt)Fa@@u7zA0a<)Rm0)qN|t*KRyz@O!@=( zLgQFeO1$K~z)+d%p)`-lvUi!=U`!{EJYGdFJ(F=lWzu6!_o!cr-n7Cf4a zuS`tbHFO+tj_CEthVIl0bI9YfA=*9k-)<8E^`Oslu_m51EkO9`A?V^0JKt0HBGo=? zFCU{ueB>odIY0kZK1_>R>kz?ojsbYBMV7QxeY7_(tk$iMUJmc{9bZFj0S_u%itg;K zIhX4t(_`cBIEU9k@n*tWIOHA3c}(c+Zl_!O)z|D;5o4b>)zf!~zxiNr3I_diQ3y)? zu|R~zmg69C&PMx|9*;GmxIgso!yC}ePt1uQKFq#R=7m|$6Q8`v6wSmTR2xv4<%Ptc z;-vP`E-V~ll<|R_8GSM0`t@t=)mL6`7cX75uRI0A6Cv(jTIlk$$;v{W9ww#NGX@+jf8RBiP6wNuNVTn^mQs`dA?Anh7e*?@}ut_r=F2<#vROQ0+Wo zu5)<7m@nDAVs?N!r`{%bb8ez70jKp(aW?q64mQdm4G721hz~teuJwe&Ts9Lh=h=Mj z(#Cuxd}*H?-(6AXK_AETsLwm=(WX5TQ@I@Son7S%q;L9MPmGw?prE(43KKcnDs5tY zR;9ERv4=_@>AJ~!2fyU7p_GSaZSLbFI{4Z_E*w@r7;z_kp&Rb7TO5Gc*#0`B}f!RcXr58+3MZ0Y*I;6OmdN7T9t zb;XAELw$3gK?^FsOy3Qqt+*|#-fokj#J&l$ZDSp+1M=tsTpUC<7)UrN4E2b0w#9>d zK?nOughYlPWL#w49B7d#U1Zpn^8gLe^3j2zWVFM8Ap4V9C3+n3eaZ`b^5)R9=g<0t z&UfrsINf{iz3upk6H(z4aMVS<#0R@we>CQ#;DMF~QCad~>86DYhv6ZY4TPS=D1(pJ zx3_%9^uWe}6zBxP7)ZbJ2}FB-7Ku9||MQRjNM7D-hYlU_cV_9c{PB1&ztQ@ezy5FA zb3gG3r)j@b0e$GjVg~J)Uu@q6UxmeE0$$={bzQR8cj8%uZT317bM&FZI&1RQSx7M9 z;;v4;y&Dh{zW?{V?|rX*^{ZcPmoHs(ta$vHiv<7iKm5n`@S~4;L5yr%iR>z>4p@vY zGv@jQ@-zCbh z&*Y~wxDO#uyrDv;erg9Zz^e^D%DH&ZzgwMllJ}C2ukZ%=>_v}RLif7a#|9+XAgvQQ z6Bz!O{J^DuLGA7Ds39tTHBx;7 zv+9h~#@Ob{c@fnY6DYKpY%rsVH)#XMru)4UT%R~$ADvvZ>kEy;2a$5y zC}~srs0F=W=B5Ixbs2&vNOqz_?nyAFCrkoLDji>EEM<*Z2dVgE*st<&Rab%7Wzs9Y zF3YFuDGC=b*?4@Pf_?io+J@TE?*Q1?*B-dBFu{VMDAWE1wGzaB1Ve3lWcf8yoGyxeM*Z7hgzhVbcdb zY;9d{C+#4E zr}nd)3p*XaR|y~;K5aO?q(^{GwsR*v`AlzF zTYKukW3$q`Fc#hpov02$?5G1}`G9ffS!G{?G49I(J83Dn8Hp~ttf#9mp!=~srCIc3 z5Fb%;3hsL6YnQdIWii<1KNrH#Ze$yed5??*-KE8zhGUrp}xvSSAG zxt{P@D6tHUjT}X{+I#Q4=R1iEO59Q7#Lr^$)B_K;W5PD+gY8?-|9$%( z|KpFeC_bdRobcqHQ1NR1t5+`j`>_A+H-4i%cKUHI41sM(B^PQm<&i!O)+qPcjs*64 z-<|vwNV^a{uqe-6p+h_le&Is< z;rGAaUVizdcJIlPegyK-M<2;uMvl2IVq?-PZ}e9dLDc~o8xy?5Ca6SYYEen7IF|Um zW`jlE#2X$Y#+2i$K9{54u4;lxUr?I>TozWYf! zhE4S`B!1#Y+9%dN!|``MNtmy6iXu|^nKz3kUG2<1sgy-hpZd>Bz(OI^X-~L-N+`0_ z4A;LD6)Nw&d{W&kjIO#1>vC#PV;VG-BQt<9Y z)u-#lwjSwMD2q+A53$ImJZ-CfLWzB#r0RjcT~988s{O?PUoUn!K+gV3)-)APJzaTU zh;Z6F%L4OSY4U(1#ZwE@SEQHPryz8TkO#`d7sgtAP||*TXIb}W_#$aq7WnGpPMhp< zbiMuNTkXxa-}2WTDC8~A@IG+rRD1B@2iw5|2RxP|OL^4^*iH8K!A6zo2L4H5!}bTb zj)R{g62JIt|9if`@$V|AkfN&Zq+2Oua`!*2?_X5lg9qBjp8J^c8`fb_wLf>(uqO*nz)xZIGRpi_0#Qm|FsE)0B-x=~e)%}-qy;r) zp%*ULC|dCV{G(4ntE1xfnEK8LDmu_8pZK)5)lQo*(02x9U1rI~GD=U`U9d%&<(0M? zE+!~Jy65eU{^2FAX<9E_3ATen!uAr!Z z5^Y>0Au9#yp{6A!5SOuD>m8%lr$BEC(3?7x58FNlA#+Tsgm}Qyb%?8P&_vL&>DcP{ zWmGHj-M2%p!Y{^JYKsL_#CBmZ#!mWSVt4y$auuYbez3Mh3f;@n>+E5ts<>QV@FX-%s3_s5VW z<7d4BN62Go`Y7>WDOwA(REe7;4p~ygu@{)DiRHF!3nN)SqHr(l8 zk#T7AK>ORTeXV`vFaAOc;lut-;r;uW4D!9LTW#w)k8Iy+|JN73&>nv9VJ(EOTV0uu zTl&C7>?q*^(jIngYq=jli&Jx1^eyt5ujdyv44~Yyq_s(A%ofl)+9k~$VkX2_u3YjR zos9#Vt{*&u8%E?w=|lf6_U(kB9q2E#m5#ei8gVE6fyX$#7!e=+i0{E}Y~}@B_NX`D zXt%0QiR0@$$9gX;bX%0<*rXUAs3$r4t7z(XJWiIyC}q@>NAF4Zerx?*H+L)Z?4q_P zj(z3f?~efKKo-BIy2LDzE1MyX5Y6P(KJh`2I-&<3OCL6g2m4Cz0qC*gJr1`4tZrk; z*#oz^OZrxJ6Wgk9$z>m2N=Pju{T0mpF>)mOKFOIbl)foG%2b>Bjx>o9(4KtSHR#P4 zeM*yMTUgsV(R1BK(n@x_n6NYKdOBu_O|=;t>9m=>@UfySl&*JfYZZ&e_jI{Xw|QVg z(uprOjJcrX$KIt68E+Eck44(cufE)PCjfMQ_U!)qPPG#!?``|-S9fs2-ul9b(a!=Z zmq2i;$vivs-C~6Z7a^cLj^Ar>y3Nbe#Lpe(mWyb zA`4)Rn|{MKodm^P7?%9gAA7nTJ$|fhU*8s4<(NTHpOd66_~fiGA2%6ex-;6t3EM*b ze!6*Wmh>u0HtEVRUW{!@+3I5Y zql9B5e;nT)Yem`Sy%#v!;xZTSst;CO!mC1_dV{D2bRY8LD23^;=(;@^LJK7nBYq;?t52 z)>b}Fg|+%QdFTKreSC+H6kJ}HE!(w`lmqJ|Ct3|k&On6>FZ9Y3dVcgN6M3awgkEb| z(2IATyiY_bXGd4i&m%EAnEvr0HHtG+r3C!%&I|FAjoU0rE)-*mlIE+RjtM1u7NzfWozV#wqTA)YL#MK1&fMF(yG*?z|Hm30yD zsrt^?Pgc;|mTg0}c!Tnv{n?+jzx&2F{BuADHxKzGGR1TG^5u5y=+XB7{Lb%a;&`-e z`(;!3gdJJ-KB~t)G=n@FywO<*KRzesi~dJ9WuwZn2X9@Nm=+-}fD%3CC4L-RWN0Jy zlYOP{~}7Ink%0cdB$DW~mu97%OSPT0^1 zzxI@K8=mT;XXF4rxEf+eUnOr1X0sYHdn-pq@q_@3K-^os>vU!dIAc{Ca1 z1!UHzN{qJrP6X-VLYEb(A{^&Do_p@xSx4x;`|ocX2M*?OXiOV6B<9&K!^c5%?*w!V zRb9z{lvrrzo_3ue4P_Gs=f)C5CNO4oHts?tl8G~8;MUg7_L3IBSFT*~#XOr6GsiSv z{WyL4v3BCry>2I8h$z3{L%;X*F5F39sC+nRLAx+vA&+COWRQ1o>}6blVVQ~AAwQyY z7jMrqfDU#S{8;kIutU;sa@V!Y*Yjz&CHXtV*cXgtTera^&z?R{l1*jW4dqMuj@=Fu zyFt17Px?s_1?ByV5&isFhg^!wMkz?T#zlB|@}Qo|3@_>8Eg;V}xAjWAj78bm2abRc zR%L!PL>ZovVolo5lh|90cu9h2YMmkwywIVlYftjqNzZ+Bk5nGS>rCD2iTrS6u_h$&)ABQ7r^Lm~awQ0pBU(F5-LdykpY7dwAq4 z8mxtwc@$TnHgwWc{V1X1qXAsy{>@PNM7W3%S5W;D1V%a(*%@R|$}W@Kx;v=eQRfX~ zp`QptGX!Q9Q3W@)Z?@}OH`?d_)xT;#`IDdYgr;8ja`51RcKFbtcH;Qa_RhO+x4-$D zujXn$qS6pEPAQ$cf+14Z&=U+VfOI^pUF#Oq_iy$cFu+ zLUa3vC$u1PlaIGUoY*s>SN2m?A$~-Srz6gX3x4P&H`flVx;WMYgu8SuKx}T`p2f18 zx+8H;tZM`C`w&RhK0rg0`H+J)F@(4LXV;TXxQ|Q(p(iJPf5t}Y2fEk21LAqc4QM@{ znk9PyOnLPo^<9oPj>8;R(KFlEQQgUm*N~YUYf7nO^+0?0;fLD;4?W}yebevN4zg)e zj7G091!6tS2}{@GcG_KJ0ukD=4>c9M z++i+<4Akj+^*wRsBW>LE71AOLu+QAZNlI`i!)An)nBb=NLQF#&z`1u@@WY< z4{(fYFPT+7JQ>=~Ueix!52v|{k@Dh9z-k6^^B`Fx5vp>nf1%$qAhmK5xlRpt!T_f>~-uUa?T;a>wy- zW|V*_gAnPt74QvOfqpahogY6cN^Gg%Tu&0Iclm3I()ZtgN|UR7d26V-?r9q=gfCxi zZ@u}3e>Q_j{RCpBolhDh#Lr{XQ(QZ3H7eDv-A6NY0sEAG2FzJ!5ACY|jInl_>`dw> znE1D?i6D3P_>J73_=!)nOP4PDacJ&R9@M0fx2PUDa=3l%t6yzzy#A^ul9ooTKI%7y z<4xKmmS!Gmq{z@}_5J?Bn|mZRRv zJDrx4hQ?hJ)9qK^x?TIOt=cglUB?gGcr4BRr}m>{fb;s)F6|zD-ds;;y-e*G)4h)t zl%7mdroUwQOe(QOh%J4qP$zDeP)Eg~>KQwH)Hdr}r4=0@%LHgKHjCRDEL7}+1Cvn| z+oaw?+9Ud!X9uPO+Oz#Q@#QZS7nFF_USt&KH@GZwoQPJH;F| zeIY=+xhTvX;7gbIIl2Aj!*km4#`cyLzxTI?9(l+w8??Os7-Jc0aVc)aFJN1pFDazh zl!KSO`Fpx=R@4!_;XxMm#W@Hly|qo61oE}tEj`m>qtabZ?I#e+Wg8tuw~nD~nLg+& zd+ShkMxS=$zb#NV%Fk{XWQ*i|=jC(3s{QH|(t}P?v!5wj>vxq;nn|7mX#>PE5Ry2b6JKKp3qL;s(AIKMBjF=q{F! z%lpd^ZFLX{h-o#x<4bUtqDy&gMi`eGVaaasb}YzukTq?fPdx0G{3y61bc|_04qDl( z4X|_Gx%Ei>Q#bgEccQC+eW6nME}nAI@4dHCE_oJFc7&6)XpHqdMxtHNeU-%Ym%KK~ zSkD5;_j>Bjd~E10T_U*FT^@QZ@S+c&!-w$1?>>VLZ8=hnnymiwKzDi#a50n6#etZU z_&!Yl9)9Q%#UZbQN~M_|G+z;a@4a_T_oEfSF+qc?P*II`57~wLfA^_jS ztGLvoK=DiZl}=v`jrAFC{LWn?O0gdw3_EbEZEWmsZ@%?r`^SI$M>pB#p+oJ37hh=q z>wo{R_SLWcjrzb<-xc1^@53sl4vDqIZXq_fT)>e{S{y#kMD0Gz{JmU%cEh^R0Urf2 zqP@h0I`#zRtG?0H^_j*V8&=TyT-qU9gM4(xU*}z>_7&Mapo5)(hu#@g7i$Q!L3+;5 z^kCMuh|otpk?paV;43;`?^~J6tAL(F=FoQnWoFv`pp!*4yNv}d-o;(YM&o_d$oKV_%xyRV&oH)nl>FVhbnY&uC^TCiF=eDlzh-EpT{KSWkX#+sK zl3w&7Dwb$Q&XW`D`x?H1z5~Ys*7d#JP%*1GF2t}5>bP>Vpt`Had(S;eUYlQj#WCn} zUdl%O`j~WK%@OGO+<(cF=`t%YeNpFpu`u~^a1H~`^m-H9=vB4aa6eE{;^|5T7yvIV{oU((EdmZNdT`XelPb3le@t|7H zy9e~f8L?K5N$48h9kGM%+rn}rx~%ee;!ZS`0S-g&CbIdU38Ysr_%zmW);;XOkd7Bl zEFi_5e-~iOyps31LP-t;CI!UnKdLGt7!;~b_`JOEU6!d>vG}`u`C@zP&9^+x_-(xmI$f6E*uDSMDTP}T zE6KxCvMeU|_ur;OIqFrS&&09XYBF06PzcZ>l~kzerW>C^4rd++n_J@RQDqP!we)!h>o>a>cgb^#yU#x)iV^3a(86MrVhM21-S?xp$(7k@}|xAz<0_(uEg zcfaeOle*y-R4{qI(YCg3w4+Ckw8u_A)_(FQKcRkbqHS+o^PPVwNxRx1Td|ECnB50| zYOjRND$OF=e#i$F2acl{>R6xZFw{jEZKUBZT5^;zq2&=%#$@~e)=OG?>bQr(Ovk^m zss8N~FpdF>Nn_`)J?N75k?J|-DhIAEY4MJ_%tw~3>nqqD2L$0l`g));Cba$d4cxP5 zbek*tg7Tt>1Z~tkW3Fe!LrWt5B0K1ud?50nkELM2l~O@c^&xI$hX9!uO@jm0YuQo~ zkb=(_bwZlu#{D{|jP~v(jN%+fi#nF{R{K$EKa@{j>vT`hl8*=%6%()Jw%4*(L>9Sx z=k%U-?aHP0=G*VKbLY=Rop|_~$|H|Fsd;YzbAj3Gh}vKK*ln!!@|H z9EQbgPL`t1JNs38ljo?1 zEqr9icUBM|t35fs=~MMx|M;KwXWxZ(L1f`a0ei+|^jP7Cj>Np;oqQ@dd&|2=LWm#c zQ~Z#LTRLa>pzg)aSwKsXL01Bd9Ypp@(Z%)TpTb;w{@Z=?t51Qg!PihM`Y}q_EpwNE`q7+ zURQ_3`bEK5J|nX8e&m^Hv0M3ndaQa!YV@_zeb88lg-SWQ_GTg0ylmy{*)#3^_ujW; z?hI#8Lf5?~@AXgaaEH{bCMJsDrFpTzQqeI+gc2pf)0y>AZNNU?^$b`*p@IKdhv11b zWzP6>0d_=^+TYM-EgD4YCv$8^3m;$c*Mj|p7k=pPJHP+_`|ZHyW;=E2!M6Xv0WSb~ z6z+jj542~VeKwDW+njW;2)57U3uM@qeHxi4+d047E`_yp<)Kh!M<%n&_6tR~RQ6V> z^l;D~P~BMsfBW0tYKIRW@lPCi$uB#+t(Ft#wX4_s!kwp{eyTnBd|uVAMY(Hp^&% z!1spLJsi==h6M!jL41ptsiiy0k_45EV?8sY>Np|`!kXZK^w$6#^W?{{$trgyNl;Gi zi1|1xxK5>R0)%Da4th;SiF2->FPsgo%you9x)%(X+%7#9h(m!c6 zUF9PCF=6d<)R;WWCp%REAk)PIr3tsQ5u1D|wxMThi(VEuq4$_0;4<}3D^Q8{95Xyx z`_8-XXgqq)cNq_G7gFWuxS<8^sZ*!g!;d~9TJ(EJBiZfo_%j#m7^|lzbp)2c*jnsS zy`06`)Q|2Q6@z8W^c0r8$-Wq-_9|DDb$Vjz$;t~P&E5@6X~FuIl}$ECI}*w$X-&#` zM|_Aw^LK#Ho;}+(4<1mK?^s8k_ez|)|73ggkw={Og$4B~-o}jy-Yr2LZAbgmjdbkH z$8)C-ecG@b-mwp+_;e94^?n@9amA_N`+s=~bOBjSkCeK?Y3(!UUxd(e-*J+nuM{Bw0QOW#vnU ztxxjt#TPb2BNyFDnQb{;2t6AZ%Zdg@I-qP>4;Xcg@*gg!0@{5h~yU2+30@kh7>Q>ul!lQdp!>xtM(=t6_f-l^wUYMi24YBI(d3@#~=((*i&v+ zeOMHd=_Ui+iFI< zE*T~OUWmXYqF)Z8GfXx4zY0c=1KI^MQ?n zy-?FaKX0l2qPSk$y4p^hINm<_lb_V&@KOH`^Y)Fc*bw;i9ZosoFjbn2T}U1+3z$|i!4j=()qW?qe5haNU$sDL&Q1IaH1t$SE;xCuDHgbh zhs$h(U5=l*Zb96xe6$7qIKz(0rxGRTO3n{;MMrcc@BS`n@)H|no$ho;CC%1(Eth16 zg*$KhMKaY#Qon2-1Ur?a*aQxp1R{HyG;BbjO zeuc(vqWAnxFdzFtwve_^%(Y9@=Thh0Hqhv^@TGMacx+ci+yTCFg(q8XxF1(+wzs$2 zk)y}kv(G$bzSKE)fv<0E`FDchN1qqYK0m;t{Lt5-&GE{yV_*xYXgM~3=EIfb-S`5G zgWv=hJKa9iR{SLo@K2?aPphCT#}V7ehySB401wz%AGp(gQz*Gnezdr(7q=^$Is{Jn zT%>Ym_(+dgmYM4>Pyh|i&V%TX45BXEKy*?%X8z9D^~d)~K)`nH_Ab+Bq(3jx;AKnu zl%%xzGgy}%`s7CdkJ&QiFe+d5Te!8xSfb+2Vq1-VTddfcQ93ByO%&{w%eSMIbxr}_B)-R8!D_VP+ zIeF@o2WQ9Cru88Oy=pta0yx<7!gBrtBhmDuSksB1qtq{uyQ8*Geo01vvbnLLZGU^~ z?YGL} zq1Y}gWP06WT_s95t~9wQ^qaauU-3=bA)3DDiGlmF@P%17lt3edHP*|T6ePK8Y5 zNiExt9?KFBW-Zz;#z_)`$e1Tx>Wal}AO`Z)9$;*ff+^w&mt;hkbeg!ny(pUOba|I` z87m^?f|*3G>_61&KA%UNVPM>uC#$i=7_sySENOJx@4eUF)^Wy@6m)0b zJ-->B_*x13>s#0SWXf~TJtsBt!pEGBE04z#qMs@D)PeEy){XdZk8Jo+e;bXTw{)=O z0%c)H-{xF~F941nzQDmrY4KFPb0;8m5@$3qwx!SQ z(^y$|V~OpxtJnS5y4!|94fv#0c4@cXAK6^le+qE18gskZtFqL`_>g_HrqUv$r* zu7wyX))t8xr|&L;S1~Vws|DzFJ7Db4IT#ijZY;kO>?#L+2cIB+5c|vZ7-cFyS*-lh zejO|`@Qo-Ls801`w$82WcGbN@S)HF}drJoszU*)TV9zMIr8))Biq6r;VF)V|p?`iz z9Q!b`W4xJ=>}y*$uIq$;vuz&SB&y=2p73kI!}rw`__yDAr(HUKAq!!}nGji}P6iJ= z_&_^yRFelya?55E6>za9F};iK)47Wei|vEk9gr=NYc z9oRhVyPf;g?i69g6EGVLCG}SQOE(#Gh6FqISY?vH$)E<6~C z6BpBXLpBT9AN=r#?R($*e!F<#lDKYoK|I@ppF8f`ZU4Rl{>hM!J@>Kp*kg}LhbHjX zuc;i~@0Xbou5!iz}qrQ6|tY2{UcXg1BUoasd>hQk23|{XchNRA2`AVUyH7 z;Xl}_Id`3D9Sbr$0iMzoJ=waRJ>&NL^O!N#FR`>q zm$Q?uB>LA5stl$bU?%A;H^^hA=hIH`%&=X@%^B?x2v5oiX6VWI6(N~W(k2Gi%vt`D zSriedGkYYNWu?B!MZkAh;V*l}7&n02O^=`a?A*C?XWHwpa_8}?IC-lxeM7QViB9oH zeLH;QPL(P* z*f*yHCE`o@n4M`Ilbro?V&YxY)yEEfo!Ic*EAB)kD_xvRl~#=T+Q@+ey*=56x(4WB@;}fk zy~4W()Uo0*VeEI+w$Qa%cc<-X%z?MdYKv>jGUVCT^mob3)k8<*D?MT-dSSG?PS_-GMb*7s@%IK#gu=VbZ}qax<1_lh5q#to^!aEn$}vfNGLXOXU5z1rS*{f+jGZ+@d)xOh=K-=Z&&gp0!LQW17-7xcq9sX>Rlu!ufvA02&iZ3F9I zYr{sqHZaJce6617NFQYaE}N78;UDW$8XW8L*};#Fu!#$OPNz+hio6ba7Z*zZWQQ{6 z@dpln^!*?RBvW_%mt&5NB~ph9rg#UXRoX1%CQ!MXYO>Mwu~F!veeK50Ep;RMydsEE ze1VBHl@+)^v!A;xUNECH#rwG{tiMZ_ue7sg&$V~ne#>7YsVBGSwD8#xwawOzZNHfB zkw+f(OR=!e@q|5d-8$1i{NGKxCq|uph*YlnU1|2WB^$v{(fWN?b&z4iapXOcQONOVdRBe zV!P>B!474%MPetp9WV_b9m{z`x*@qPwhwXD&Q#yQ$1%(Pb}0E()^&piAfK{s(UfJo zOsZ_ZS8gs>LIUCHqeMM7UXnTI)%4yYsCeb*? z1pDslc?bTOaYk#kJT)ccy3*-a7qi(x6fM?2VUq{KU_RvEQwx9UKC)&Ly?`ua7 zA5qawf5#3Ux<mcZF?0+Nv1J{+MT*+we{?FF08!;0qaa%2(1NuKGwuoBIO! z@*^eA@zG@#L|4#tS=o$rGO^Ino!W~X=q0<%Q}pU09_IAN@t?)h;Frp6mZZx3Ger{c zOSXs~a!Oyic(EN(--hfr1^e;;=<+yu^M-gXw>P!$J@fvVER=OTdCV}h@AYHx#WD5p zBagHPA9}!xWabg}QarSmkL6y0Oi-~EU6kihN6JhR61O{@%hdm->5+DiZas_ypCav>E3yjWv{upZ4LW@?Lo1MaB7spA6zWaN^#3+mnw!t|3P8 zN1>IXkD68O7W?o79O>;b^Hv)n6TjR(v`H$nBdTq|JT~kV<5*F)qa#`wLkHS0K7=;g zz8%Is_<`UU@7>;x*oz+Xkm!8Mb1bv>aSd6=o%@y2G?Dk_g{{sfMbK`qzVF4q4!Eq^ znH>MSW3i1RS+@EC((||wS4O?;i9pi)Pe&;|J(iO8>=uRd1cNxbHmk&MU_3_GF zk|7(}&@JbS`p8j-khu}_^n)il(_IwybSIczv3p~W4WKlQwhn8`+`cQSi?GT&(sBiI z;E^H^&MY>%oyCqE9V_4m9QQtNa9&hk-#U$%?b7-C!Q2tJv@J@5H|K z=9_KM=y6~@CN_i)r9qL|MqWOcj|oR>^V)4Hl4=y7ryX?_P8cVm#$p) zV{r#G@#W$HCP!dCZcsN_NmT?cJ%_#a^J=rGwkV-Zi?cv` z47Qdqk;RbkMw&j;=dPm97D!e5K_BY|%+FtsKOWUs!`C*djgYJFfx_iJh6U?O{dlDL z@WDe~utM^0XsevBhw!H1ciwrYUAS;bdiWl3@59)Z9TwEk`3+yjod+L$K-+`s5HX-^=*__nxhy^F^ z4Ba04h3|0-$vGhw#xO2Qa%cU9VyKw##147-sMs9Kz9-Lx&r26BwAWvMqite$y`#e@XR?*l3eI&Pe-iai^ameI_VNAa)~`W4k+IJ3j9X_?vdFi@atNFyKKnvab1xKicm^CnJqyAPt7bq{cLIy1YB*Q!6~O=wHy*yK+=trwaYUku4g z9zDL0H3^Fs5xI%#r|-TUdIf71!8A0Tv1dC>n-+9SfO&~NcIbfg9^=2FFR~%=LF1DS zrURrCtEhY!eSvk9y%X3BvR%idA5vd@FJrVfKcTP`8z!#gT|Sm|fsYWSeemWsaBZoC zc1YExtOp1uMN+~63wE-z6a7wrj-BLJ%Q#`hYU0eKfPM8T2DZrgt;cFKCJqcDE*|P- z-TGip`(M{W@a?zW(gH`5_We+!YkPakza#tL!w;DcbCmk(-KfvIxzB<{AMrtSmpdC? zXf9vsS8EYn#Wx-s>wu42Ti1O@8{Q*_5Bukn{`61&*mu5p^D+IIJKt9>U(%v?qy5MK z^q<=4$4@KI!nmI_6n9zGUiJuUpTuSZy+Tud0P@|>U7sK^Uy_N*`nt_^W-Ghvzyy)W z<954xZL1wVd`L9$OBNkmn`LjVu8;4?5vvOqFSdXD-uK$8ufEbQU%G7Cz76h{arM}& z`oE<TZNV1Z{CB%`QNeuyR24*Hxs^L)|3CKr z!`qT9z3u~}(wp+OZB;uE=mxvdO@ag#AR1BBP%~>N&7UeQX^lh)5G8^DNC*HyI06l# zE!vbfS?OP9&HnBEeGw<(-uvFmtgMD+t=#WLoO3>ZOq_@l5%*p;q7U13_T7?M%Qn2A z#^x+Z8oAIL>v6LS=DxZZkp3t(`)k{Y2$He%2l=>OWU%`P;QEkR{H{UVqpx*2s?ab6 zJ$aCrBb&MmKFH4XN&mSWprP1#?OaqEeQm||v2U5sx^3;Z?XoYrfoQ2U8Q+l$g*|24 znT7bbREYEO8!UZAeW?p?9Q3$AuWjWc9sXzpHnqET>*npz{Ye|U4cdHbfu{=Mnk z6X)Ely{L+7=G*%d-$(f3i!V(tz5McYQO5_r&ry6S7W3bcIw5kgZ6U!vOh%LTDH%6PWC92c-r{zw$x!CtmQgIFZCPk1|!{lqWo6Mbf_>Qf@!B)Z2f{( zZ{6cC#*;&VV?*Z_8R+hWo|Y=ZqfK;i$Y3Ks@(SBJ?`xOSq5K~JcGGrXpX|23Rd!ag zJ}@c;ByDPd?aNPFI0>uv^^SdvFE%1mrv2RwmO9dY@aOqL$Bd63Vz*qbP0)kxO}+Qp zi;owGtZ%Q4dUmgN#NPe8Jl#>- zR7^R+P)8HAflk#X?xX5UA@%IOA%8p&DbHq{Z_U55?rb8+Az z1HdWcg*M>H7oV5rOU1tT{qIe;Z{Lyr8C~4x2@H1Q7kl^pGcfm$?y22AKmFn_e$7w6 zSb%d)nAnu*__gnmK%d$cz7=EaMk;djo9Oj9U$+4n=W}zz=CNd!3&v8W;x*swMd}i7 zY2S7OZ61@$Zi7*0;kS6|jB4|bE_v^;lnd!!j8`E2FzdgPE_FMi!xO_}Nwc~~ss*-iP zDbLei_%A&7-1M@>|JAEcd9my#95$aP+&zb;O@r=p(BxE$7?aFEK+GmZTme`v$8nh9 zY?LbnibO@Ktq4P*E+sOzJ~WlmCn}eJb7xs?%Ewl)jD-cJNPjCcV|I=q@=B?avbkm` z-P+L)v?;8NiImf}_49wC_1h^v7bxSmnrLzrs2i}$)P#(;&?rDnn*ADcUH35`DF{fF zwL97)KI2_TrII&hjsTth?YV-yYCMX}fEYU&6VY{hluqWl(N|=}h^IY$YDdYih*J{Bkg2J$Mr&| zk7L<&y0wEW{Y~&l_V*I7MIT$vxuVJxEeAr$RpQZ3-h_`2yDR^5NG>y0(pH`m6pNn} z!&i0u5Cu`|5K|qOkk8b(mJOG+g2v+G&jjyc{Un&yauXfjP9D%61*nec2+>Ry-FAyV z=SyegZE+lL1ajaQSy(LwdT^ZvwmR5e>YqHw!869IeEw%yU|rG_jnP)yi5}F%IobfD z-{z0$Y0*|WpxU=GO;s@m;$bu|K9^XTZ~*j<2YShKfjLh~4dll19<1UkI7YP5&%vLw ze#vQ~G@lcf{QPuN7r{Q+>uQm22t7NU^HWj#v48rElnumZLhF+k2;XtLsD0TO>l9YoTF~N+ zwTyh$Nj@^+%_kOJsJnfY_Y*8G45fpVFUTW^h{TWB~?FZMcP2c(Mcc<_E z^>?RRcX%><-ml5eA;<>4`0OM%4lZB1IQ=*O&A*r~U%fotxqURt#3%g{lIvS>sRkm? zjHEo}(O<%e4_;%9f-HI5br1q-sYWuM10oy$3%bpB5NA~Y_~_&EuwM5a^2-=rbaT;- z-l9A9xg@exKYT3gsjp)$U+nFoe1%LN8h7ClrL6ePEL&Ax>YwpFS3%$%1NQV>%GzuX zx<^+53FM%(J>DE9ks!?V$!5Lw%fY9{xQOr`amR%f;^YhZ51S7a_>T`u+!FASRk!|gL zh{S+J*)}s?+eY@GhFAf*)!(wH?)?8R-IDqQu@~UB;ex`2lzX|k?TIZBD*ac)L|?GY_g?Jb3015$3%}? z&}{{p+I;|8Hl$_DgIRY@O*PMGUCo{S(E#&X#~ugy5wlETTi(F^+I(bPOqrOI7tsW5 zJG_F*C3OIq6F917e{&tSn)FYPt@ckFYP54+S2_7{+;ygGxu~-1Uo_i&1gN?@LYa>B z+EbQWj;es;u0yOgA~ivE&~-`XSFGij#TNA=`|1lI1{Yu3`lpU$S~6*)GV{ z*WUIca@wSwX(p2`UmlX11(EAMp-QfiE)F=s@%QHIZ%x;(ec;8CFXB|+`$u=DC$C4FYuR zIZ%~jl?4>k3l}d=*R@HX?pX`x2ETwe`dOH>C$xXh?;&heQ^D{T;A70_`jLH z_~oxmcW&MG1r%n^@Cu~tyS_0i;0K}-Hvk!8&M{LAZM&F{0m~i6x{W29LWUFu67J4>@Lj%q9j-IimUj@YG_AN*qY0OtPj?y%en(m^ZYr_-6^V_W&L zrDTPzHMhUF<#n^3%Uo94cIoffuSERuW~0-MKllJkw&oRQ^bup68P*kI*j6G`7DelM z!!+f|`bk2|3+9$gY=@uMj)|Y5_zV{Wl=n?I<@xOT(cL5ePId>zMc6xUz3tEY-o10z zpMAgAPhNBo(Np=@kjARgb84f@m#$71uUwv9`P9qPlTTjt*!7}UQhiK$t`)(bdABv} z5swOnWU7unSYf!Z2kzcZ%kXTBx+zIa)i=p zUVLcU@#l-}M&pF|B)=?zQ$Kq~crGt<$O1TQ@G{;%QMmu{l{&>QX@fQ@N-B5)h#9%l z$OaiVwB=IX_Su#On%=s}6`)6K(TCi!Wsfw~TKtc&32YT}kI0Oc?Kll|=XO(`IS0^8 zL-)HL2`q6Hee18|elTqNWE@u=1RgsEW$i;5;yQ>PE62$khTSASS4*jmf`F-JTSufg7&WSy7^4M0!QX+kDmnZVE1)svNZ@iFe^W!Iw;va z{0G21xZ9@FVk+ByP7UH=!GWCKQ6yM>U@!$7H@uvj$eBbu&cyn zGHjLX)awAM9uI=$xRLJQGO%-RT)eTUluDxL{dJ!X*2ZTVb($c zuNLy8jBk_v(ck>d^qud1$4|@9Id}e?e=_Fwojd+*>i@^T_^+ocmo973?a@J6ScBE_rJvZv*jCFb^; zYt=x4mfq51FBm(Z`;!em@lrQsjg2e}iTMVTW$@Nq8R&pg{sF5|LpMtGx7S~VJu$l{sTKGGb*Z^^q45S0D4y&MlLkfphZ#4eJI8_pLH zt;IIhw`tg7Yc&0nLi-#1_i^S*)VaOna(t6N4d}zMj-cyuS{o;$Lrs29d{wQabEXud zL*~@gdK8H3w8lQa1mn0CjP*?0QrIe^!v?+Eo<1C9*Sg(id|6&xLNDKp1>hojV6@f8 z3O2@L>hxIkS*88OR@n88M#wVD`6J)fGe| z!po086THQ|2&O}FVC(|wdlkaIp?mo z+0zr}v=Dyh?dik!uj#yc)?Y62S?vZ zx#{lF-Rb77o70CMUYq{$Kl(@0-~Z*mKi#==x1RLyG(tA#kjNy?EI_E6&=)745ORE~ z6X!_pw zzB|43=38p7+y2R=fA}l^aQfWmKkJ`OI=ai}D>1-P!a~9Bb6v}VKz3LV11~sa6W5%e zeFs^a7c|wbe)S%6rZI-gAjAO~ljyjljeaBkwOr6P4xx3Fa^XPmGq!qLTZ3+D=2C#2 zE|YG{yJ%~0sS16+3v*YpDbu!;bewlM2J-^#)fxfEsuz&T+amswGa+T!^|)&S{8d&^ zVNF;SNmQIcex!Atv{Y6tW$40*zbqdmPhC)AV;EQ%nxu%=$7Y>V#N^d~zV-P#-}$a@ z=)m_)Gl82jEPk0EpM2`6>G|iMo1T5{x#`^5^PXdTb4lPgw(U#yJkQlQ@zZ1c`1M=2 znCXs3vWbBreSmI`NAhbR)w=Py(6Hf}d*4XEt|;27+{bzf=5+hyIMId(WmP3rYdLrw z18DDI1<24V1>z`X(`Hd%n`w(&ILBi5W$K}}sSh$!q+ezmh(XkR@0d+m;*CBxHmDyX z1qGO(GD-2lRc(k z?7#NX<0rve?DAi@O?;b>>}>1wAk+?d z(=2;{z+s`T_PsXbB$H(*^r8CqerU+w*5Z!WQ_u5?Dl?82E%#Lq7B4Ik`3xx69mwYO zGBjzQewu>a4WM!5vHK*B652&-dSZe|q=b_ou5*U!7il`Q^0R{iEsDjXTq&OBek> z#@DXO*tg0T&YY9XJuRMZxm_<_yx^Z*V$s0QI^o+--c)AZiGL|-0I_gq0lmbH(c?h9 z9s;f_;o_I$Tz2e}?KC!9w$VDzU#DU#j>@K|c&K7je zVbEuDVDZ%!jiR|P{B$Ax;V&C3wGk`b8N1YRo~U)tYz|&kBbqHt-dhTF`IT}tJquU& zss)#^#5czOr$7G-#jTM>oi*5%y-0^|82Z%x#VA0v&oca{_=dq8CY8vdn_V_1~cCcOq3pA8F`T?+aqJBh3EDTl>?JBkteNqo!cvSfS+74-6 z)y%|wn%ZC0dF^7K#s(LbKfYfjHDm4fu&s;vsw74E}B1B_>9*2O1IrE3j$~d(kj_iTzYdS9Cj~H0M z>5$ogdgl1Ej6>=^!zXzxu>t5762`F-!#zK@9c%_IJL-!m0d9@m*TS&doO4LJe!s8f z1}HnWb*1bZa@k8B4y5u?q?EBe+F5*^ldl^$Z%#jb<4xbJU>ZAr;hb-{anrJ|e}MPO z)6Sgx&Zz&fnzvlENq{f$tdu*3 z)G6%?ZE4d0+0hn2?s!?68dnXZDUyQGT4SFMM30RPdVHJ+*SEcHfqpr)OqCxA+Fs$< zIJTf2w{6?HgH5B`93ZpSTaFu0=V^;emid{YL)*p%58D6*wl437Eoisuma4bs#qyDu z!Xvq-@yguFwV0+}{{knAVz|hWdM=UiT!ToU{J3s)9(nxj(7RYIg8P8k?d%PZTXj~M z80ZfL>H9No>b+APyh6u1#=cKCV&S#SVcCIBs&f2fz%@eI$RC3Wp=>Z*rAKxLwwi2V z^btGZ@A}=<-2$DyaKX%u4V%CQ2YK7-bStZJj4UF~4D#mH6AhEe%!NIG4j*h}<`dY- zNS{f?^$nug{Dg(?K$hq2ffoEEuL(F|s_}Ij2SM z@BH@fOuzekzpF*?Q@*$|Uo$p8_jCRFwdu82Uz`5vKm9NLTI8KOcVtI=UkqZMExxji zXnLmyFvK+GU58XOXcI1Td_^>IKwJcKK}@-nEYkeSiof)7WZl1|VzmEuR&oI;+xkQr z8`x4aR$rh+$Nc{9|K9Y@yYKm?3ZI+2t2WNbbn@qk`Hj`*UwGc%xXVvl(U&Z+`6-&o z7qRa3f_yNRJbv}J_c-f#2Q85h?Knfj7P&rV5TY!Yp2GZu+U=VSp8E9%;?F_Skr=dLX=r0HATUN$?DpbQ+O)STW4p9} z;*N`I3u))es`B&`k|ibN>vd$yW*0nO=?9en)Z~dlrTf@6!8fbSR6XwAz3bPSuV24m z(q}&V89&J-phTzm>?<}$xV_Y8H*ZQ;fnC&?;|5^*mU;~u*z<*3(|X*GGE3s{v`ZDe z(>7us4K#h>lViU~k9y&T)_P3?)MHCq>@F>?vd6V^E(hsfX#9b+0b6xu3{^EN<45@= zX1aFRSC-?Uc~H`?*orUzcDcWl?}w3B84+&MJ@w?1)8{__xrxscX1wze3%KZ$c7N|{ zukJH|KJ~Tp0&-m@?byhcJ?}(hOoCLp)QUFS*bkp;C6l&Zq+7c|d#A;s&@H2KG2K&m9PdPl* zujN{HmP0TyZV#6m%`23x=ulQa&hn(4Cl|dQ2SJbhaXc4R<8eg!oUtvR4qZ1EuL&vh zLe3bBgC{1P)shr@`r?4&FR`gmpXRJ zi$uJmnRu6Scus3E3L)JBCv{l*8QK$Cd$70`Jh`GEIkHA&B=5e`UrvL|#f5)1gfCdq zg-XAo?7Q)1Z`*&2vhs7EHE+yz{}lZJKpnZ*;&XogPK)6G>-T=opKm>X{`_?A`~~r` zeSf-r>$WeB|LcGL&wYV?_wJEH3OF@U;}DkI2x5b}%SqkVvAc+9kr!VeL}ZpeYK-~x z<$_U`bS$qN90TOp+BSM@+>PGah<(Nc7pr`$?#&z5r{DUw|0ZqAF|F-BV?rry?Wb-^ z885to`kBvsW_tPMSEd(Vc)@+b!i`r|Sx8ZJU;GkJjWZTXEWI-B$Rk7y%MA;+8!3N^ z$$cC#?LxOi+2le#=jePMnpZO~C>9Jcbb2G+)pc>UQ@FRt~s8s+d)0q5QY3b2Pp8!F$u&@4P+TzJAlM*kg&GH{%A% zFaF)X>o-_Nv@P0xnd3~-##kV}&=f`(RD1;ELjSQrJ6O=H2Bos{NHE5_A6wqO2*wz< zF^{sLQ}tb+ZMSskRJW1(PD!^0J0Cx1GS_3r&E|L9Esd1NjuQ<8#s+gSV~X^~ja$?A zzxO@gbY#Bh!{bQD-)BDcsp*B6`Au?;b$-U~ZsrH~2R5=S z#EMlbjzb{4W+zYI4r8oUJC0q#fUV9T>w}}pICQ%V<7x&nttXJ3=O8fp9cZ&nV5MXq z5^l4$R}IAZjzw*Qg?zAPzoN2P!QYGcqz+6u&=sbQByo+NO!H*gzpL`w+?pT>S zWVd^}IWDt>mGnF~<>~#%!b~1eFt1 zO3HV9V_M9}IfVe9Cpa8}i*6MxlSCO$EJ}1BFLm$9rpo~Rvaz~Y+Bbon1f~Rh&*2b& z3S8XDUezz?IEHpvl@YJFJlRlJo^Iqqku9I|9OGQ#PupN4uLh47z74!#89{FNo8~ly z*}aPVJPxlb=0a0`?(>bqc?EA5Wy~Niza-lW4AZ*&@E|^7!Qh|$@t;h;_wWC`Vx6YT zSDwme0L7txH}2e4Q{J2Yi(mh>>F<8ym!?~{?zk?D5ib1sd@J8TefEiSb!|t0Y}-Cs z!)>4-;8;!N?q_&A-{$BOrZX;5@VIer;46O8wB@_cD$cW$UHWwJ)mX-j=;qUJ<8iP? zY@idrBN#hepu#?XmPPEn>EEe+uYGu3dKm-g`h@8IC1MuE8gbfqeG$t~Kl8L-Re$A` zm!?-f^@@M)3UOlM8)5kpBih_{MDvo9n5iY5<2qz>OT(+-UWd9t)m?4c$DJrSjWKdz zQYRPK@xWIX=g5?-_yocm1|H{(SMpM#Uc_v($n(#IgN(q(HhK>X2aM5R?9=W`AE&en zWYIhqKvj&?)lgzB$&scG$}3=hDG}`mdp_n$Pkj4x5t)=BaWjL@-ALe;@Yd?c39xqdSt*F((=S{Ec*3IP>c4 zx4!i)-$>zY4u1A+y+A5BZrWpMv#tXPBPr*L^h??cFuuC1jD2In%)pIZZRO)5*@s1| zjxGWyO+~6D)0RQvUu;xdGbM9O+95P$=lU|Qv}EkkkI{~;1)&8tMgNl0j(j719hZP6 z@;K4hqQB4cWrq5H_ucoVpZxfz(?|S9yC!3MJg19i_2oq^cE9wcFNwenS1A*y!q0JR zM`VOCE|~aav!GDUttbPq0QQopG-H|Z1I6`4Ri%h(H}`KF*@Kp8?8uJu{6^O3`oJRq zf~qpMkMsQi=s9Bt<&R{GgfSjNC!=)$dhHbpeLR|N0-Qy*5jOq9_|crkJbEbp#gL$U z9Hn?#SdF+CGtwm%C5qPU`J+Yd4=COlIj)xZBK=u>=0R>2&VB6Ql$4*jZ>cLjpf?R0 zCExa3Zu`iNXu7tC88_~moM*9tCFiMlg+bB%Lf+@!#K7DP;2{_}XA7Kjlsv)l$aTQu zFUH!3J&WKp=p#pUtowH3u`!-JI|4_868S@l2VlMOJKMFXwl1{Iq9eCVT=s66(Q}(k zexq}YEQnZSPpZ!na~WwL2hd#K@gMvc?Q2U1;=$eVGv~#h$%}5+eT|ldUXzZuOh_@Y zPj8%DknM@7?GzqjqFMC~*_C?YS_2`rirMOnT^1RlF=?3tuO=E~NiA#zVX+N43lv?p zYVpEP;h;B%(ig)H5L9YkFNE&jJ@V&4ee*)HT$C`kXt^ze z3*hmyPJk!>_9{6R;w)^v0IqS}V}qgU`ijmN$j4w*W(XrIn#X$7T&64UYXQk`U#E#I z!*UqW5;sx)w;}e-G2P+(Ko;O4ULg!eS-w@ed>hcY75r}@vf(7BN*3^Rd+ho zwnsf}p6lWt#D&VUO#~PI#{s4R77qh%`^>zOt>>6nL4r1Po;aKDzDz$^iou}#xG*+g zRW>)sVvn1I2q6cJ@f1Pr6q4`fk*8hS7&lRn6rZ;S-g@h;=|_L_W99h*!}=mI`Da|+ zyL)H)@|V6iJ*i{==;)4U*pNT9dHO!(rS8B145+qA(5CeK)on6E^x}A1AD^3k?J-hq zmA)6oa?6|w$c?h`U!nd?k!E2W9PixiH@DduZNtD$M0ZdUR#^JQd*{JU94h-w8rwY- zC$z=J3Z=INq~$F{Q?y~{fUWlHKF;`vX=3A8GAXEWQ5ph%Dl1*;pdMFVo9$&w-Exct zDK8u7cRgeaep#C91KmnWReby;cozp2!Idl{ z<7b8*7$f%47C6vk3v-G1rMFZic5)ChaG(W;d>rRHc5o4!hhse6&WN@(qjaqA+{Xo0 z2KxhM-}rP4X`?xwrdLe1)I8fPdhvndMh%{27r8as4uH=gKFW>!kAaFm6QZY&(0Af$ zf3%5JgiOStLFhh3Ad_q7(n*{24C?ijByu0j=qz=@;N`5hyz!b|9jQEhJ=|kkhV}kW%ZoU>>h`h$=%K} z7)r7;pdr(Ud|!Yr{AyqJO3W&RiqtsfTDNtgADiTS3Yw*ZmTlbzdi&xAZEx|si^$G* zt@Tek`NHdY*g!IlIR`B)BX&I48OsK+ujHr@b z0r@Njo!zn>i~s`>%&0Bg`&NOlc%!YjAw|3J4fBbdJ*dT{3c0Hus3_n)A z5EehLLu0es!v^e+gNi=q)o5OGzo$j+wGXrC{qV!<(+AhypYGhfD|ctTkWT-^pN}_< zBjU_>(WZLv#dv(d6;Faa7s(wO4o9*hY|d>(|0k}X(PB2ZW0`O6s>S7yjC zUa+CR=sy@%rpm=(Aix%%0T${2Ft#yNToPZ*Ln9Hz2hB2%1mxKkTi9TPwYwH~3XK~k zALXVj$Cc+Jj~8Bp*0C-6cfRwz>4OihY4Ll(9mcrhTmJ9fIhxL%dt&;`r#~}2_uO-0 z^=t0wo7n1DNLg(YH|PLJf%5W&Javj%>u#~=*pK_XWl7lvyQ{S5qsm@X9V{~nrV*{4 ziA!jklI!tjjCv#eXOCr!r(O-n>vFY!l^ckh*2WfXb3eMBM~@;PKKNUg1uKziV=n8# zy|M$;M;=$?5$-anindX7STBNU(H7iMI8Dc1k$LWHafh%zx1{=twQW&b;x!AM-O7rCB#J+DM9b7-jE}>|lS!K3c=P z&TBit|5&#fqDA$vk7xy3UHjaeNM^D!YrFQ8?6DXpmmKh?(<>ml3R>G(UKa!eGSM{V zC%-d2i;Adb0hFqRxQrFb#9wh+&^xya6BHMqX;p2R#bk>M=V`ie{ln?{jq83=!xOqE zpMKgCrQ6a^oHV^j#|s%0v~l6;cE;t{bStz!Z4SJ*qR%l4v&;slE7{9}#>`!&Y(jrL z9en?tcc+QFur=EINi?{lMA6BzA*ihfAWu~^O8T(q72$aEUD5;a816P0WwE!>wXFJsJbmdn=@atn7+38&BQfsU zRe7gzs}ACM%ru*mr}`c4IbM^M9zUP(!3Q5qZ@l&9^u`-+Oz&wy%xA8Ni!tIwl-k^5 z2}AnlOR{)s$l8?~FPuno5}l@JpL<4Q@M$fIUzwhN{`u*g`i-|3@^o10yk5!c)6zS4 zfj-S~aZhou7-m7{aoP3K_{FaCKqqJT=_}eOH;OW4E5pg#V;<1k=(!ax@06v%Y+Ll7SY=!vd2-_y>Rh+fwJC=>$=RhB|s2l=0;2cX;hIa^W^O zCPL9n?$i=gmt(?16TP%$hP-w)2bslTrA94DX zcIEAlS6}_SzqOm290@%!FMT!EImczku%v7xm6n|yvH?kLB9O~2y8uW zz?Q$n$Cl4=x1RPg>T#jscw#PRMtGg?dhX`ezLd|u(QL}2-VDm3BRBif-$(b<7A*YS zXQZHvkyG{zzelaE;KG-uyzjsN{`A&cZ%?nk{>Jp~yYEi7Zr;>dN^O3YZ}Qfn6<1yq zFUK3`n6SY&$nu1d-ynYa>8GY|eB&F_Q&*nyPcp?lm+m;nT#lgCFw!u zb#DCfS!SN-;Q?7R_|hK-Lwnn#G$6Bpv|V~$(qzPQ^=omQP(_o1+ljis&u$mU`+}+Z zIA#_=5To0`zjs?QSnMw#bGhUwS%yWN#;g~T7HPTUX$SuJCss4KV0ZO(fdiFsi2(94 zO4}mF4Iy-BL)!lKjhp_w?hU1Ulk+t#e(&GAD+yF3NB_!>FAk*}i*S{v4qBoEn(M6R zlxe#9I3|VURzThjwcqxmM>!XA^Puwfue`&ryy?VGsdb!$ZP^r;IpA8) zbTnHX$A<34#>!^#9~SmQnu2Wgbrt;@q>Ty?-N!l)R3G}7ut>?tj&BHAHrD%XtmtG6 z*^XtHKk^Z?0R8}ukyQ+oC5#=9A5gXpXlz|>bPR*7Q)20hIf1Ifo7h?0W)Acr-Dt9hfWY&e9ry^9_*seR-$9XJI{4lNN-uf7w> zuIWgzfr0Lc)EO6pmL-1ZiM8u)?I*aL7fl5>A$D|i&ueOLzxj^oEL4~b^Cc(K^yf3R zV*mjE^hrcPRLrwa`_6qPNQ}%Tm9JMDy}>vMs<9_d3^DOm9BwZPB;?xxSlgwYe1YTw z`doB46T%n=6Y@uA^O-a)sQ%#h|6ux~Kl(#mw4Kuh_mk6EU66T_S2+B%3hnyK|KJ}? zKmYT;ARqkXkG;rr`(uxNw$#Bsy&aBuk!e({GukGoi*BEE7#GUcRcS8dBZW*ZgmWTW z#$$ImV_gV)Xb7&4d_n^(VtJ+gD_{E3^v%Ebt?9PL zYvux6>Q8BoHZIR|LifT{Re|T=S!pR{?4+%V>G6{KA!^@B7ocY&DOw7Y0;&2ZH#S5< zb{>PIY_w^Ed{q=kY30*K@JU;j9<)N|#y+PFXghx)m1AOOYUQ<0;*#}B>bNm*?f`%yj!UziEDN;`gXM=Bs~rx=$txq>hceGlJU7bt8{2 z*D9OoXt0HrxhSv-z}Vb}i)^;0js5wk(6&MQ3v%2qep6qST_@^nYN@DBlzki{V&)#C zeRAF@8QP=VX2@fob_(AlGR%vj69=zA^VSC+Jvq92&p(IeaZ@_H5%An|&rGkr`l{p^ z7di(?kFm$`&9}7kGg#bAO@F{-lRj0j8I@VMkbsISggWl5vh+(tOGfP%e)l(W#E)*` zw4D2$JTx{6CI~9KeWJU@V8e)?#MPBxBfreoiK$qYOFZxoA*`iOfaR;aP#+BKb8B}j zABWS(4q<)_a4anGt`J5Q#&!oo*+Hmm(dKubP=-;dZRQ3|%xgFMkqzgSo$WwloQ!ee z8}#_ILZ#@jA=7-&I?V^jx9&dKlQH&_Qy>2|?x0yF$1kCCE+8WbG3AHzr%Leh_K|Oi zm3+q*9yge23M{|&_;u(V9DW`85urPK?DR(m50!+>*f33~daQgZwX}r`CFl4kH;=OK z#H1MVgT`-f$qs1$hit)hq*hl6xsIz*y0b0skaO{P-91>^30YfPp-s(byRBj*6WJDq zwo)veP2ZFublc9#U)%Pc1HELmC6vY1Zu`=jZJQ!=#-k<@vZgB|dX0jT#U>M6D;Dgq zZDWIS6_rUWW3`e$pqzT)fI|xp3kIXB1c*VZ~2kCB#YfgZDr1Q{uPZetUZNop+`iw{G}k z$!9

a_H|D8_F2y`{1F@+&V*zxH4JBfn-%9Qk}H3+edxoo5HaqU?;HQ1Mjw&h0zC zk%LWa-;)flQPWNRNapD*KOr9R3_e$Pbl$43GlFH8@pJOdRX~>t} zid;T`=M}X>ScBjoAL)#9fB49hadGWnE&#|&}HKyFM-{_SoSyw5-XoS*Dp zICnvGd@$cI*Qm|ar@V>5c;IuSSpeRju3!I9$KwUrxGXt5#8)m_*%;@kJ6rpAVU7#A z1~l3sx)w7^o&ZKQ=56P(S@~lSdwuMk7Ra`IJ0})=HidrH-U~P=H6lxF)L)MM#=`4- zX)A*)4NH5Ar{ly@rNY}lIo2VD$IXnl-g6$elHmeX_gY(}!b`XgU+AFzM z#@T3$#G=qcqupXh;D%H(+G4L4#Fn#8*Qv}P*Nsy)_n~#sNV=0eFnXRD@gTN#$J&Ap zcj1yt{Z@Ka?{H4%zjc?kB@a#IvbUful0w(!@zZ&d$Uy3_%mV{IDEe#{K-(un%9wyh ztSzU_aY7q$$adop{dmmnUFq0oMHa#%@0-R-;jyrFyD)EBgBzRLYp#IrYeL6THc2?f zMSJz}li(dZ@!p3lg41Ab{Ls7kJ^{!w#?#B6JjP0m^*rGJH1+oYJWikyN6yYV+U0W( zgMpGm@{rlYD=q>ySqIS;WowJs{}wBGCV)O^H2HuZBNHB54r&xqHrn=qn2yJGG6L9D zJK+bj?dJgy3)!N*)OTC|pyNKlmkkdwx1%K^F!t{2VmFIHI81KPxge&AShswr#mP-w zfWq@Dkh1Haj*$#cPM?1E8R4?k_iavO@@|W7r5~k)8>ki7%4zK%@K;Z-O1gCAj0BhaOgQ0xtb~+ta z7afN%``pGgO?U6y^}^`lC2p2b8_8*mSV#ZZ_eoK*M@MRN)s-*M3XM6)%StbJiGv$2 zZ124DuKMM5e@6Qj-!?6?j4OZflKSqZ`uH2a^o{A~zxGuxg74N(HeEQ&&n#(N5sYHd zrM55DdHR3t+K1Dh{@I`U<_6z9efhE$VNX9jUA}s0x~c`)<;#~88(;86L;-R0Dzz#ZGW5qbQ{FHylLa-#oWKrMUT&gKBGnNb2^sD^OW$67SLyetO4d@`Ul_t-t^Yn?|L!J zH^);~;$gAN=Yv1>@+;G4KmWP1iZWwXavV#dVUM-qN3zE&(-$-*>0^t+*9MSY7QtJ< z)86AKs+m8nEkF{eX#rN#9VqVdX2Vy5SMZxvfXg$w7j(7HMO(I5Wd^w)p=pB?x4^O1SwQ=iu2_m%0n z=bxWmdF4~CN_6*O93SKx-6!a=Q9eADbQ&erz7G#D-6J8V7kzw`3Vh+Mdv2N(@Kfhaeg|`1Fy$SR%D;@&ac}+05_5a{m2L@a71g>E-u*X?tSz6Jg0S?(paO zyPjFdx!treEbblgP12c9TxZev!YtaHH&d`@kl@@X+R*N~2!Tku zjL|b%tnvi-JKy2k2pY!E`(eFQkpR`FnyebneGEvCtxqF#GrPXD=2 zjMz%t$kOHu#(qtHS7t%RV$1%^PgYb&&0j(Xk`b@?a>>WA@>Zu|%3N zjC0>iw!8RoyC^K5_mJa!Wsx)W&C!tqsQQMu;3{FYY(M^X=w0mnVk~z`~m$65IUHgSvXr0Drr{MOIM(PN!(-BQ; z{w~&ai~d@Y5?h}rj{$acLGI9Ito0MGHWK^BXC_Y5oFH3rGZ098LGzJiHfod~ZL_x9 zk4)D!`FsJyS$}Tx?YH0ZQ_*%odmQN^`|8yz)3eV#tFk6Ro-Ci^B3(j?+qU$_g?O%A zMT>giG3Jb9d9@VOxN}S$Ps->n7Zb!+@@SSkX`TRAo!iz7l&V}TJ_E^?cwf~-J4LC#KSCcmqDe>&2_gucI^#WlQH zyu#0pE%l9UcB7LucI9m7AyN7mbp1fLf5uGOJzJW!#u8)J6&mLRZa+BZsQlK1;A9q( zKC0|&&xIPYX$KZwe6bR0EZ|tg@?`dMeb$gCm#8FU;_Y!^s$KEf(KmIG{_p$n%RI6iykyq{XJ z`9fB=gw`7!Q0ct^IC*6?i3TBmxNB8?%vH8h4Fc8 zZu;=bvdc&PQ&Y5y{uBzwg4;>;;K?fOgFjv!CqDFO`)_{pn_93wWqEf|hwHxO-xkv* z`r~(@-+J@S>Ac_m(4tg}o-0p2<+modnc()&ab+KlLE7$Pj0)J-0pKZ5=r3Ifqw*v} zFw2++*voMaeU@{cJ_t=(mStcq=R9=BIVb9|PoJw$x|r#CbB(qYD>K|)%>%@U%tr1M zNIY5W&A_zF#7Lej#~bxiwp}Z;KHnUUqbU|mLsUsNRMy%qyoUOcHzxSa=QrMXYkK#+ zcRX&m7{*V(*>T~*`ROyC`P}sEGtc;K4aSY(K-+6To2Rcpd^<6TT^EYyO?&rO(<{-K z3#c=MoHr07#?q|K4zy3-r_ekgn%ks`R;fbwwfT%GSbN4w@wKZWu`FfaCb51}?V--e zN$56+4eDYe4~4_}#|Ja&b$&(D<{NvW#a7#kP0Kr{{YnN3G-M!YSNzx}4@emgrRVb? z-odCNjJ{2_ahFP#JOh*r8v`GZUwp+*pJ;QKNGs}~WLh@yNe8tR4RY+R=^aD-rQ8R8 z?}fI}z*gDW!gh*3ryC&Cx`*;0cWS##iY-#MJtw|`U6z`)97+*pFiAGO+py`hgJ=|m zK4a_tV&K+T zVn3hs2!llBJjDXrIML|(mmU=2Gq!sBWP*_GFlLR)lq_NT;#~D$LTAyz6NWola9zB3 zMGJ&_+9EybktbMOZc+!uD1BRGL0B<6ZmXos;)QnMGmX4{-p3bl^Os1_u$E~u=s(iX zOG;Uekw}VWALH>lr1EWr(p_Uq?|j=3=E}8?=-8x@`bC#|jrnycV(oxc6;Z%=Q({m%5{lUlUPF5?iNOFvLoEkv9~pEhD_^y}O)8*jwULdK=q`2vib z1o;;2Z+!jl`sb&-U>>@Y_Ddn)0!K?|(~;%ruE({#IutBs8sC zioT_lMK4jenadDbzsD?f6Rql&J&+aAJ@%YhvN+IYl{G|UE=1DDBx&vWS*+{VKAgV) zgYQq*bzbnz4sL`<(7!LQfpG4^h3U&*`l3Jk%^aB6Os=kbY0xL`1!Z z{xL~qj~|Ue&l7Gnr?WrCjc+h#J0bD9NP1!JKK&kGTKVAXxkXJaJ%^UMlZ6Ci?Yb(*yLbC zGNHF^bYP4NNfV6ZB+K6I?VPsw%JpW?A>>oWX3VuL<chR$uc50jIoP9_q9)knA=$)ur*vjtHTMxSMeLNSP!Gg>< z(41~;!QN*dTl1i7P==)JKAl5o`RHiVzfEc5WZ{$nYsnnYt4)6i1%By4v-|=dEG5G} zb+3b`4;sanc>-`q7*E|Yr+wuWaFllFPQcItupI?6YWk2=eRZ7~y7oU>h z0-Y}!di$-n{SCk9$7Ae~H_bX$^;4sJN175fdFDcq1SUY@ZqkRBIzeAW>?bXfSG*G9}t{C!c5 z2g=B?=(>36l58TA#f;-ozj`r7QSynB_RHTAaK$gQZgabxn!iBh`2@R%w?h-!w%c5~ z^F;%FLwvb7Xt~hIuPxFRDK|BJ+8bqjxGY;l=3V1Mugii^Hf5Kt+XJN z_DNowioA;Z(hDz6w{PC`7xeJk*F2fxvx+ zMN{QpvE4noBdw48rA_Z@5&PZme#d%@iu7qBq=_k;Rz76hPj&zFPyc*+|NU!z;>`60 zZ&=Ve?c19c+q`x0g!BCcVp)hcu-bbCs5Z7!r`gDhq%qAH=8NHGz;nGwGo}NziFm$o zM4q}y=$`7%6ZO1?o!7Bv`>5Ga5y;b~N*M=yqiDAQtzScK0K5SfSmuuA&T8%1X1#$L`&jGMXb%u|N_5o8{jmf!9h1qY>5<(1`*HC^{p0SU% z26`>E*TxV}W0w-3Jz7A{(eAS=TI#yyL34kLJac9mluqfZNKo!$FtN2~Kz}PQ8S9mu z#YXg#dOvJs4Ry+GQpkC&^0fuYVJmjgjKAfYWq@twBQln?9x?jtRsxKd=tph@{2{Pe zXGCbrST8Lqb^wtLpO_+>>y*?bQ8oHTZ>neOiPSqKHl>|1oy~E{EoAn}7tQAw{c+B| zAH~Nw22Z^6!L^U*l;t1^I=5{?%Sd)hw?3J{#-l`H!|OQFr95I=kJF;tz#u(fgK=k0 zhtRMNnbK2vj?T6i_#8;EJVZref`JvuxGnuUaJ|7muvped$8-Um_J@qgvZpO4m_i&> zfns=Ld(G`qZl z>BSdcm@ZwqSQqY5c8)RU^o(ECym$A=pS^s7^F}zswoJ=C#?tQS4{=!*8tu}2?-zOR zBDbLYA!A;S2Y~$sU6TdzS)UyII;mo3;ltPcfA72BoqqD;A5CBX#@DBpUVPcFhx2*N z{;4G{AaR35!ppHD8VeTet8Oenc-*#8 z6j8gJ5xT!|R`Kv|vm6)MlIt;wK2N2&33Kh*2h+d*_y3oD^x`%m zvW~nqFU(7o1YX-pIhhg(C~Lbn9VrSTiQO|=OmkD`h3B7}e&H8>!Mg4{#lzwkQ&z-> zvK@!>@Z2>y{^OSpfFXT^RQ8ajQ&i@smhN}|h|!+|?H0Ue%RnXTNZE#P)Cezi=7KId z-41hGjj@`Co+a4{>IX5SZK>$aARim0czX14Jd9~zGjTPBcmfb$>xK(jcS)CVuoo@7 zLd);!(QM)0}#DX2>3&vhT)NbzkM)IlSwlBx=0cfkx((f&I4Cb-RuH@a1^0!C5Nn?bKEHbLF z!8}G&kfHs8C-&!nm|(}TyBpg+Tj=aFztuez4%Ooj-Kbcb?_iYYxL@(0Ya4CNd3Z%r zx*`L!pyy*C5zp9RyfxA1UGwOh_8%j2e1>R#>nr(;t;Fg%&*r!m%=J+0Qo;_p+S=Zj zH}LytG4{LbQ9eBeO%c-C`9yAtMYB3*)7v~5Jox5@lU((gy6jP z(&Hz=TkQQzaChL`c>?=t(>35DcS=Nb86bzy2SCfE+=G4%kCmnm@vP`4p$(69A-{3x z*VS|odywsKkv+)49VjL1z+we($_pcPtm;+wMAtFvxiJb8_CMV)$abSze^M?$JD}Jtr1qffbkzg0v%q@M2E{XcRhb`{Ic> z7Y^_c%NU3O*&prPp^xfNcrn~p< zDt~*re*L;>e9QPvja3$~Jmq9@%+prdi~AP7sQ0VT6l75wU;YPw z->=&P+RZbE(z%_flSnL}c}o2UfA~lF=)uJc4jlW~=E9n)cAY(zRK_yL5o==~Z*I59 zp^p#?lFPh}aPEoeX^q!Q$`dQ~;W)l>>9W%E($^J^)z}3r0Odd$ztA(Egl6lqNxyjL ziSJ7w7t(kBys?VJ$c0nGb@#uB67)@2%B~m!IscILUgR;B5Jprv4P!f&Ug^LVeWqbI z@{2u13JKnd4k)8j`Ba)h0saVhBkh3f-eWiANV&BH?YVk%+bsHonfkWe8a+;uM^>4x zw-fj<%|NVRV(6vMo}a&CeE#`=`g8x3oEHn?V~)2ez-yoT{Pf~0FL~Z%ZfmPO7CC;Y zc48JYUZ+vjNmXiIx*+;e<{ zaRShZT;$s~S!GUP!_7H_*BS%Kw);5fI8TFpws6Kdzs+p@?}v1-Hp-Hj<6(Tq7S5oE zWBC~+zs+~OA{BdxmzH*E_vj~&G-c%}k{}1wqV5r&XCiK*b-hWpw9!CdBv=RC z$BW=y9Q!-L^MEV5JG9ajHhRY)V!Jl>+C2&7m%EsBbRX#McpTZD3$yHq(PyX2K_(j6 z?SyI_?$kqL8+>>J3oT|PEmrb%r_$_}Z#nN4a+R&GJqHB&Y|YyP2aa^)W3S}biFn-x z)H9QzgIR(!X)k6uvO_x!^hTGkcnB*SD?n>aVoY44yEXd4arC;?-%%1qKf&DBcGlZI z{pR%r!{~>t`2}C#4$v6Jh3le?zKgWvY9i($fuEas^UXIT%Yu%DKqTFV+Masq>h#=m z&q=2y-9^1F*b_(EPP!T^b5unOX6gZ;E2$1zX&*!2xUm3;nTr+wPOSLE)lc6Tzg*nM z8vF3BeenMDfBeR8PIq+S$Ati|*515zbNcLOJ~RE(fAUYJr=NOyy5mCQX_Ah_j@#agW_);^T6!ThVzMSf=7R|R!=XY}NYV0tk z?@N{&8~EdMkh})}8I6gTUVcG5>LXX)IY69O->V;(->a+sFQqa1PiK9=~^>-iHct!ru53m?4z2EJh;LCVNx+=)k@s$M*mrfj}n z4OzxFRx*~Vajes06yOM3UEZL1O0m>>_?^!)wxPtV!EV7ZKEW3~6=5FZt<*Y#{cY)E zecGqs0gvp6whJQbxz*0owjGD9n>UwEf!L`I7F2e&=(B%(cOE)7exC5}GynNt{3p#_ zm#Qt9Kl#nzC#Fw-`qR@h{{47v7BNQ4hwDj3@pqnj&@9{fk8QGcFX(_w<}lp;Ekn98 zprQw?+q2`33>f5Q=W2(F330|=&~hO9>6^B-hIyJJFtYgG#cX4!$8mNWZEv<+^2ci( z#y+1Nv8h9Rfy()xV=*K*(@KY|ZxCRS|6Cs zlC&$?aM|Yubfsz+Wceb(SPOmpm^${)*ai*L$ZY5X z>SaI6@~yzVK&O6&=v12;uqa~T`h)L(fBM&21Yf>-#TR-k8dywxc>TJ6e(AsZFaPQE zg)e`_3nzZV)@JO769m7P%R-6YuH|Q#+-edKBZ0WMfU+462=v%`tQ-Qi(=R8+sH~m;6jni9utBaCIZ%)`dfxh8*CxDVFDCngy)m=VS^zt`Z*?P{eD) zLP;1sMgV<-^zB<(tZEU=x0x@CA0S_rU+U&~R2dd$fT4*FZ20+dE(96NNx6q|@BWeB z47hjn(e&aAFZeZg#tpCkm#TIcAVUq3h2Ec^vR^GA_;M`9PA_1QVoZ7wtXNp|vIwRP zh{bJz9VNNermd)(#;wOSu8(8|Z>pF4@nrkx=&l#f(1@SrI!j$yDDw!{PvEtoW<4xq z%+f;CfW7NLZ4h^!tmLHc=5@V^2@Y8kOEK-7f(b5xk``4tvs$LTYAf3f*S!`TM)Mtr zU^@B1uaCdt&uE*Y>?6cppSz&;2_-R%RF|{#vkuw%687CQcC&IcYqz+w7 zN`|qqm0PgLCfyUNAfoMz`uOS_G`(eh>EqLw{XRUb?zlLnuphIJ9FCRDgU6dWD0SaI zW@)#jPxHm2U8X{eCB`1*Zfl`pa?-Rd{JC!Fj{GQ)@&Cdr*{02MBcPM8BW_Z*Jy_{0 zpMR0Cp^b!b0$ViCo7yrr19Kh;4!8Y+nJYQux#1dA|5cIDvjA4=^IpzN=uygp3_ch! z)TP_OI>}PK$BW=y99#r{9CRx`a>E;N!tIMK;}JOa+^>PQI>?p97p7tzBtwxUY^J$K5U=93nYx%2?}%F4xw1N)5%31 z`Fc{#F^v!H5;qI{Gt<$X+tdI4oB#XtrQ{kB(ImcU-Xw73u@RM;LXm3kx$=J9{GTZunl8ygXJQFSSeFKXXexv z$XlM0@)QSA7q&28^%-~`o{E(bksN$3IWjJ1!v*9*)-H~67%^6qx$il4=}(f>hjM7f ztWOK`&B~GChDA)MY`!+-afz(kHAa=t=S3FH`IuA@JBfp~@>4HX%I>C*raQNfawEtK zz$m&NwnrOKAPa%4{*sj(apnuK{Dh5opnD(W7$d`f{;A~=>vGWYBMrEbEuSy!YPplqZ!9FA#Y*h74bslHZEeJ6nSC*ao{L)LSI2V8kF-7T zctj3c+SfeP?Ub7~Y%PO7B`0F2!weMJVlQm~{jlsjZ)oGjCBM1-?%Qv9oZPs6b9(Wm zm!>D5en!VxK6h#Py5i06UZ;Pt?C-^>??CX_q~7*l`4p5WzCI`h`(vD?LcL%w9Y?9>Eplu1mOWtKJ>+qp2?ZIm5y;>{fU(l*Lk7kNNE$afhl z$jbLvKkL*&k!|+h+ajB}30leSYb#^qkJwY+9a-|7Ze>MPe9iIvUiByJ1*xGI!9GUe zXYNC6-e6NFS3mQWuYWkND0%hq>(D!RuthK}st%%$GT^H{i$1515c?*ahUs$WL9-Qc zI2ur*!%A3*-AqxpW@lfvE18Hb5IvtQdl;aV115f;#dz1R2Y=|wcN_-*$5V*KQ=f>3 z6O^svK)sZt9cLp0$~M_!;`z83-IL-sSo>VsPas{fyRct3XdW2zjUA%}XyVOn)G|e% zZFRX46*FowVFjb?2BotALd%EAg%AtiH(r0k-wsVY^djTk7s85>&;CCD!t?(2*PNy!0G~sh>_$i%K`9d!~ z8~6YHpa19S^`E{zJ^l1ke*Kii3s2Yheb;O6zdyb5^2^gd`)B{v^uo(8`5UzP{3+*F zY;tn&>(Q>m_Jk(CD_AMn8QU^APA+3LRfopr!jSDUJ&0`EQ@SV{-0}4>&jmU>qhza{ z`{}0d9wUtjmz64SFJ;p0i%$9Q9yS@&h5KAQBhyMo$|WLHj>K`~gpNh_dB7hT@3nJG zmPuJf_oHuyoH^@p+^>TnK$5Iz;*s@U@$uQ=J2&r4m#$oz>yy@8?7KNMkctvJ8g}-h zV(Q1!Tb|6GwQX#qy~L|nsW}&sDX}n@Tnt1^8Czof@(0s|{Ko4&U9fYZa*i*0Q&2p? zMo+A=XHn-F`+dWv7vWEwDc|>Vp@(VoJ)C_QVGqCLv0@1#31LR!PR!U*0TD0$ijIJV zpkW8(SY4qESzegWB`GAG?WdGXZ;i}TYg*Y^0scr=+3f_ax76b>wsza++U{7DlhMAh z)%HNs(@E|VFZjl`-1?_1zMT7u?leGn4WDsxSMw#h94{OqLG+2&H@oU$8R`*Z%qAGs z>G!l%!-QmK4E!B-^B^X_+*Bbis(3 z%NjMN;4bJq^+vXZJCy|eDVSA0(CbC$(k{tF&JyLDoiifpm}nn}w=if!40h#b_6!wD zKYgU*!Ti!&CQ$)KD>r{-Ot6P!XY7})Xm+GQ7Qe|mu4=Eg1dUl=QZ+>?RXyOl8qgtW zXZ@%<&zBzhnn2s*Mer_a^q&&dOLL<)I_r+FKAQ^5-Inp(E#WWFKi^@a{YBOgFE8=nHlD z*cd}y_vGyyC5B!b6e4&=(mP}qJ zK7{5at_9F3AJW~>?PH;(>AN2bw5M!_6n~U=x?-gpqML27Z^VT3$t*nUS)LsYX)kaf zh9$II$Cw42QWlLxTS26mYJTd{G~azz30=l2X()K-CJr}h?)%HkELXA?LV}ebIr>aP zKJ8K$C&Xkyo#3^gWFdfa#t(FhrjZ2cw}H8F8?qx3ui|^LjZMnDV{I$FVLrZ{5GFdV zn~v>!9N!S-olvl)ZPvEw#DPCVX@h_T4!kPDA9(XR0NYAjb8K-jY6_5??ZQid$oM-0 zm@mZa_?6+mv*ihUA)R@#=?j0xU_WU2 zans(mlOL2G0E@l+f!J}mV(%(~rtJrUr;B5eYI~zzVrs{3Q*DeZ#@p@NM;iC{Gj3bY zZQAkGrhjgf@?8iVgXYQRtg`|-(5sJE=yKWBwzSD2o3W5Bd}KSp?(X;r7P||!yv8Cs zn{keq7Rrpdzq&v7$P{MLV=%giy}+Xc&p24StYD?4QO$j?BJ+t^AwGP!%#7ks=179M+OKI{jq z287V@?em8&bT;~^dzmr9>uITb?s|)cnDfMl920oQfGlNFWGw8wp)!<)>u3=SMGr9f z^`a#8zNd4RZ0heLzuJ6%djI|Rr}y4_Ph(%U&+w`!lV2j|OM0Gq_L=G8g^M!4=PGTa z{E)R}6?sDCoOZ;R3w`&^{F){^tMzXnXjn>FCGb%FRMwp}5rv!}j9eea`rGz3@rQCc34m zcaEt0yojwojkAg?h_Cr*l3Tjw}g_-qXvveEYoJ>#u6KpczgK~Pt!GuIuPquK8r>Edea)dvlJ-oWAxj<({y68PY`aGMB&*c)jLo!V#jpa*qLmIM ztIRe6X9w}*Q%IcyQ%W{5dP`Q3UQhUF^{C`F%kPJe_!AGaj*^lx96 z5JJv}E*d?zkMh~TwoICSX(W!ppk?qe>Xn=wGj13U%2QNq%n``W*H88_qK=Ik!$H}b z>kBGg+a2kE@<_8#vPS#d${j-aI!?A4I`cFKaM7f~I14)?PCaRpADz*TYcdPz2zCF^ zM)Z%UnhH7o$uBk@e=*iR%!}apfO88D=?ZSqWB4BrIZ$!1&L0F}RF-&{<~XM2;}wX` z(+o$tF&9~gsmD0!9Pd8^(ta%8a>}DK>t^x+^Q3O4O=C!p^3cN@br#8pw9P$5+a^h-AR^iHyBUiOvh*kERbkcz=5L z-FGd@m-+bfky>Q%8A3ig_S92PiPvq76>0gR7kjyAnqT*~3@073@n)||>^DN}V$;Qv zu^dLjKMd-FSmHrEdF(9klfHQ&l|>xC8O)bqz5bJ*OuzA)zcIc4{T z^JHuw6-d(cS}xS0Q+$=98Q*rm-iZmO=VF6AG%?{rH#3qRMrJ`!Au6R`bB@Owe8y3Y z{{&*hFXW6fidG|Mx%5fbdy6e^pX_0MXp5f(jv`r5{I2gOAha*a4d|3(r~7p7+pa+8ZLi~{Oa@(!S1k{1wtEcbF*oPQMc?jDVPlI~qiiMCpDo(w*tSr* zOd6SGZ2R~&lU>uTg}QXe_pw19#9rJ*C+92LQp9+m-!789nJyysUw!GRIh@A` z)=z@n3Dr~8iF1p2ux!xsb2pNOMrM!v2^a@2*p|2O^ngso=_t6ktqYo2ubCTgY%do- z5F*5$i)8Dw6~A107fEOklP8&Nsgx4}d3Jpv!WNlKPLyYBwE^NH5l@+AqGQi67iPVJ zSgCiFOLxTBwl+^eG}4Y8ndD71ZMHSq9Pbz4>T7+89UYu#=Q+Bq_=M~HL%`a&=m zE)<$X!jBg%{4w%#&3%bZ+%Tt=mn2UdvN-bk7 zaZra_w{H50Fh3tena>?^VRrTEQ(gqyopchT3iu!#8#K|jI@?9~OM4G!TI*9JzoKtZ zvg{>iiH#h6KwY8cCwBP!q)OF)9nY0Zm;5>5-~7%0efr@K|Hj{(diANR{)wBsI(W;! z{mRMUTi^WF^v%EbO@Grgui^R$v+U4*3=~v49_qZc2 zRA_s0-47K%{>;#ZzR!WMRGu3Qq<-DDiFN2t>#xVz49Az7c0ubr3^!JlM$q{+C=ao@ ze@klc*JC0Gz1cgVJtUTKhcWuI?Z$YI#c)rD(bgek44l^D1HzRclRAK7{rNaTHsdn! z2V_@z7GNyVXK9;UgYLJTMX=;;vKGMx^T?t%`dIvPJ?)@|{d6tn!VT|Gc$Q?0m#4I3|tyBNn>j<2+Kw*itu14QT_uZ<;wD zp6jPF)YwYR?yEk$Z4^c%_&8B)sDvoK;;;%B6=J^(OV8gM399) z%Hkv0k=E@sx0?rS2KXA3**vTbi`T&dR&8JQ9~=buFnSM;_R>vq8qARm)m%V-P;K?Y zih;1U)sx^uh-?-WOTXqsBAWGk1NdoQ3*8r@)}xHB(u%7m`j!paPU^6fNwAdie9^i> z+sZpa_e)o5O*S{V7$A1|qT8|faKECwd;-n9S+20x-gTC>!=Gnh=PINceUB>g+zvO9GWZ1@hW0c*1 zcAh&?+1bYi8#%+VIa7QJ$dnw3`5kY?Hq(Wnej#SY0}i7LGqBP2fYOzXv27Z$yVhmf z(;lY=w!mV0-FERqSi61J7~>jooNPlp^#|wQ9z}5P$rpzdKUKth%7TIz_~|abG5yWA z-kjcf`yJoBv_#~SffuV^yY}gvH?^th8 zciIgd_#Hz7dSW1Ehv4Am%z()5(vglli(Dv|V60ErvkPG!dO@Ga-nf?`NM=3R&` zn|F`D7;7K)FM{2W57Jhcc(iScwVlBB#O1-DgPV(14TFpek$O;x;Fjrls@t01x{Xb_bat?hen=LG zXUp)9lY0cP<-xuW+Qt~i17hDD!v$rJNpU`50DDVz4`QQE0Q5B(XeO*D!+e&>f+3jC zSZMpBuh?C|i*qvUvSkv71}eiCO-{UKF1Gr!b!anbdeT2V;&Uuu z9FgL0?rV~+;Q~lqMd})v#OSzSL#W zOU!`$W^d3#05o%<+_TD~<8G z?J0DdLsPoy>!#Nm7Vc*&EwC@f1IGhJjuHBw65u?6M+9WG_0o@Hf_1q(S09|*SBoDRxZrTFiu0noz$bgR=?#Saq zO-kxG%DArVrhLJj3gwTZ-y#)Pw_VmWf_bvdkkH@bMer`P2);%er6(T|+ER7LCkHxQ zaWC^h%1&#sqrDi1>$W<`WQgCG9KSqeShOKp5Kfb)5CxoJne)gaT?-Gm3 zqkNa0c5&C<>_;gUS2Atmw3y{>$+m3Y%utWREc+ln!Gp%>8G~r3d#e*GHt55SdD|u> z4AnGqLmOob^)+l@-r_TeJ}jFwpe_2LryYZ>ey5%e3+Tm8)Y#1q;*67!v!z$2yvXe@ zP(Yb4_aQHxr59nPU-{EDSxmZq8Q+WK2ni9!T$cr1KWrWc#NsOj_fw@ICGXF{Sa9&w zSq@0*O)kL29N`}t`U%!5RdhUhireFKD zU!Puk?KMAr@y|5*go$}<4*pIAl_5zi&f5z8=E8!iU(9!X7hh?=#l~`RQL(|V_Mp%5 zqzReiBMCcWuKUA8b}km}AO>HjLB%t}WiqGJ?<$=L39S}dr^PnD0X@z}?4vE9Z5CTz zMEID6#@2b{7}L0C9K_}-47tF|LK~T#M`B+rMI#m)*vfQVf>;@g6e64Iv4g|w{*3?f z>A9rsHX<8@o<$V-ZMo4gpx1PzICpW|b`J>5SZ%T25$?AOmu+a9(_oHQJLhAQg!zf5 z!7MT83asDdrkl)Pym)Rpx_f_mQYF5^;p`f|1r;fw`>EghH563CRC_~Mwf_n1%_%Gl>E z)AC8pS;;+0V0IhY&jdLAxOEzAq`ifl{e=%^nc{8Hwqt+cH$5P2A4=yrcSP$(XVH&dOqUI%F&)`PbjYpg z-9`a^u~Ytt2k0EUj=AG2S?J=I^o|FX!TADGB&rs*y=LpluP!IpI_3k83SLX|b(@_VKcfmXtmgt`TGW_Np#h}x!5v99tX z?KF5;y$xDZR%B+=PaCwmeVF^`5FR*AWcN8EM$#JMgWY5g>4D}gGK)GpX9UIr^lpzu zCl@F!*9dRfNF?hEd+elaa_`Ah+`AWVqMNT>nWpH^n(zcw;%D`zDRt(v@i{bN<_laP zh1Kn(f5fGm#V}|h0u(#X$%|~qRs3Tig_1jI9D)2m{NgXVij|Z$mft0;kEU~H&-)v( z`7Pn!`ZxdQ^wZaWI$gYUX}Warg6J3X(;||)_Te?3RQ~Zl`bX0jzWCa7<vTHW-_lBdi?ZR9AAgS5J=m@gvP`2bhI)+MReg~e z%e&ayhl8Ej(~j)}Xt`tLPcv?2oWif!n48^3e!q{AhTNcRG@oN5<0uzyp)K;2jLx;W zAI-Kxq2%WjM6O?R)V`<%`yAxw7_^()q~{Xy*sy?Xgq}I9Z49<7hyRv~-Y%Nny73eL zT^@N42-k@iu+ei>u&*84<+@+D{=2-PQ=Ho@v?IT|tXWch;HJhloAP|G$gLZ{bJeVbKYvc6tYEX*T>#I>JgB>VVD@Gf>=hjwcT)mig_G~_8FmJ|G1eFg%h zcMz5#bAsFknB}~OXF7O}j~zTRN*ynGe*3}!Bcz=Tq__>=2LO7c2QGji&7p(RNjB82 zZnBYM>o1y#kwM>kq3sNIoo5^Df-XgJ7qjkzp#ALe_h7*9qQ8wJ?KQ|8@^>(vL3c0U zAu~WWthLu3pzQnlN+Ub^m~+z0MIhtF1eI$%+HPprO5au4gU&POjBW?S8detul8~o< zvmZ~5S=4#cs)&g5ErPP43$e5H?Cf9%92+;A$2hdE)6j;QEELB8ghX?LmQj_eJY8tSj1@`nL>XtU7@T zaY6A{_1WkE*O?4*%J@(l4Y6QUvODiDV*A=`7tL?~^cl3GJ2q(WYs^-@E@x_6`g$L1 zeHBk`_$=X3UlA;mpNq09Q78X;)>k(S~mL54dpml`x^mqVH|F^)7N*gmpJyq zbr|_4+up51`Xt!;?D9Ul$P`~$e!KkM(MP`N=4&DSpFP8u5#FEPdFSovr$2o|^U0l> zM{_*-%d|8HbK~me7hjk@_qkWCfA`+q3Y7njWx*Jo`!@%_8F>P)K4mU|XW@#I_}yk0 zCQUzCPT1dPYaoeK>&%dD=oBKg&s=Mr?CF$nJu1IsR_Hn=DpQhyrfpxnsmIO&?j)R6 zZiA>qZ;T~m#kabKWDKs)Kj{nUp<1@uPTK&-^{;J=@hfk0DyRLRnbXP4+vdTdH_F7t z2>767I}cn|extG<=#>60#KXuzzSv@I&jo9s%Z5-3Hto^CZJI0cziDb`k$C9gk8;|8#)=k5j!+`}rg%a>^LP=w2g4#b4SFij_AS>6IyJo4jU1%HlGwEU=QRsXq%1kz_j6=ye*k@EPRAHpmpT_831y1jbUwJ%COf4uDvzibD5~>MMe;SM-;k zJZjJf$w9xMMep~%``zge{;z*Oz47{6)42=hr}G#29avqko;`2-ydM4RvrkX|@?ZXU z`9iI-@8(zCVqXPf@Zx6dzwYaIbLTK55QLObmuaa!ZJ_CFQIIzJpb@>LYH zu@aBr#-4goLM}_l@a8e4qHVAn;2|k~Nqc`t7I&vKuXegF)OX}QaI>8<@Yu+{q8I*j!tKl0noA-lrC zx&?_{GStU%y#Z{3tv)fFREM>V_#wC4cnnCP>EcuiS6+AKdk462$eeoZ!|T)E{LK%i z8#k^`{5;)RwY@*fr$1VsSE2c$!dG8?ZF=t6XT_6u&D~xe&-Lzf1TlilITf5NHoY*n zA2Cvdzv&0djD0a;BRimvx$S%&KUFX&?5o2mG1uY$U%>cC`;2YVZ8hVVdO;mqEfxZ7 zFislFH4D;g3v=5yOAMmfL3=o?yR~szwB=C~cWYA)!nx7UsGE4v8x(rw_GxQF!f|4>h%BmfB(zr>)-r_Wo~NGOS_$w{yAO1^0P^2 zWQcE(26Qz~YWQ*+J9g)dpbyf1v(GsV&lQ1WGByw)M$+!Xw$pj!vO%+QGRl#!I`(Ep z>8aedqK~ZloXuUi_LF?J87j=j+nQ17!vhO!t8t+G&bTnGvbC{8&QIkFZjS=j9(Xlhz zYMIKroPO+pT0M5Mkwu2%&lKO-%6N#F1(YElPdz8b&fkKj^Gr}7&_e~*vzO`Ez zgm=cq4AC_fSlqV^soSlv(7ktlLB)Lxx>>qC2FtcdzqSuaSpKcI-kJXLFaBbB|AY5E zuhD;e#uquxBlomuent!5U-*Szn4W#+87-oD(NUdYQS4%GjEk|8K(OC^`w??Ke=e6! zjfFYVSw7>`S;*uE9~npCXUn`1UVMxje&#$*Eayakj&5X{KVuPeezCJbwd;ezo~s?_ ze5Js7=Z3U0o$kYICq<)eHoCm6&#Ek$ojO;(Ddtz+*vbpBG5U)Pn~!zpbC4qy8FJaW z&(Vvs&~lz=`3-C{^w=+%4Q=6RbKdNr3g*Krht?r=smdk0V3cU=qXE^su4~#%ZXE2& zrbTK`Kl>b`vgemv%LJW{h+eXz?OoZn8y^FoJjcJ(vEW59PctanWMrK+0R{!2dWz<6 zl*YDcgY5$B-S&J8u>W=F>YxlDHE@-?5mW4gC}`QnsFxI;Qe>(;WGRJz43PC5RWhZF zUdj>>&GUjyDZ@W2r+4a$9D35xH1_ixLy!Dl1SxTsjo;-XU-ik|#p z%NI4XKhW(*9{-WEPT5-54O>7o$b%^^j7;EP`cdQFp$SqIL6a+UbzKsRi~%ixud@KY zZaIIG^!+0*44-@UdE1M#U~aEDJ_^gpBJ~k5|Ai`)DnNc+xBc)5yDkR#JHxkNN{y4; zJ0S+FH-^jVJ$495mMtLnVrUNK$eLXJ~nUFx4> zzY4ZXF&DNryhv(mT7!NBBdx%>tH_C^3z|1-zUbI@?Sl5JwAix_gsr&2II1=vSM%$( z9fC4iu#QRVe&{?{>LA*zn#?G-pzEy`I5gL5P(+m-l*nZt_k9^kJ+Uv z-M>&JsoK@x9&5_i;daH zsS!KfSHWT~{?>lIpUYsBOU!Hjh|w0Zb2D>pVBGbHHH7$f9|p<)}-(KIu?_V`Kg z4(3I$+fuo?g{p(L7(4M{fFE~G`>XW9PzEX`9@}Z7P<0|Q*X2dl7#%yHM#&W2=Sbx( zszDji#ov;5AuuFCDOPwRT|mau~`#h_1UbWe(Nu= zLMF6KQ}mt1tX@2Tj>>ba?sILHLmk=3FL5Nk*%rFC0dI)S;yvJcOlkou9@|I$nU09z z#!n{tR<96yXQmrBZcNuc_#k{JToCK;=fGY(VL4ydkM2DJMn2V);hESlRhVd7{fQ8fksv(k?!8U_ixMI~mPmr;cpPxx^ z#FTnhusm_=zIJ`A8kkN$FqT4{=K_NYv~Ho>BaJqfS^8t5CG%Z<`fIsD;)_&sTIX*Q z^Vo0$bsGZJf$`?zx-JGJZS?7CtUz-{Z6STS%!38HD$@jzy!e2;sO|u}OFRScsl+TF zhl|Y8pJo={BMh`bSMz-bH&d31Bh8|z!!U?d% zRy1eZ7U>>Y#{|7~+3KKkegyQkH}VeHp6x71n^a-Ms%^%xBdpqJw84&T*H6&=5s{4z z>XEkLrW&)>Pk;Q=>Ge0>@SJkt;w3F;6^mr(KYp6+p61aPo_l_J^|jahvu#I5%#HA| zr#Mw+zRAaJx(=NV^Qg-z%yPuleG4BNe2veV6PJ2Nu94T{(?-NP3z7o2Et&RD5t@AZ zrb)?dG1@TVVaA4^V~pI!-j1CC1CNB_gMzWL9B1CI>^5(UwcdK}IW-19C!%F{bjU-e z@09Ih!88)}t#taBV9ygq`p~9)9TWa6X9mh-7u~L7$~L~EJIbqo@S^A4nm4Cgh;9%2 zcq=gW@ku?~Wb2gQax)$$rv|#6~PTJE(mgzYe{NohQK=d&>a+IOv08AC>`nG8|LMlDODi zDFTB)Q?>nZ!PA2(d<4dm!5)+hdYSv}A$m#}L{O3Q;+oVX>Nng^6Rn42;R5dZTc~>uixA1ntFQdv-xq+eb9FOYMmm? zqUwx>67(zxGvjDxaScKbs_aEiC~LqU8M5XJpnakgoTm0z&0d;mURB-f^mV{|PmL1Ynedq&>JC^Fh- z-jS|&%xQi67F&AE`!VAg-!{vR=61iTjF>jpSABEi`pxM_KmN(|&Rg$DsctaHKIdXi z759&hrYl#jPM>+@Gt@V|iCi1tx9YEq`_KYGuAKU~j^DgW9z7KEaf-Tj!v;3>hpw+rg;!sEya?W6 z_jTw~pa+VQbif8Pzse8nU>|UV!vpEHB!Hy9Hwbc)Wx}YupB`}G ziftAJ&|Eh%2hg#0`Vh!qM}5?XwzkIrCzg2<>lg(m+Oe3KKTEfb>0`tQy00Gur`2)Y z9bb~;(4r3qCJo%Ejk@#QdeEz$2_n^VXeQEtNmBBV2u6bwn12vA4)UY7id4A zeYI@ox!_Cw3?m4WD)Nod*RFjy9o=O?7jdT0d-sm~+q+Lb_0;s-bIhG^oWf>>n0vgMYxEth{}Y0rY_dJfRv-q%g$VXw&U@@V-HyZn333AmpGqg-0yQt zePZETq|f=)YhH0=0X;t*m#SNna!eS~N-8=zo+yV&ol9sBU}5Vxnf<7E2xyD0|4uvn z>~ZS8t61F*^g)pyIb^$^jub)Lp*DiPjihPBS(h(!8y}KydhtAQYa?k}D~M*>YCHCB z6XpVVE!%19m+hVTs`(=ZKC#Sm;eOflA^EEBjM3LV-4Wrnge^&>e||7XCdb0kN8P-0 zmjP%)86Do-xOwaLbmj6T;+CYrfSH9+S3(@VV zVzET$N%dEwAh4Y|nQhK9sof0nf)~NINg=cu#e0;PttnGAil2wTVr$)3bKec|@9WP- zM8aR>AhKni$Oc9m(DvDEdh0YwRtdQ!oEpy-&o$NZ#jMLhw;yDLQ+X7*nV~ljT>T&{T6D)W;##VEjqEoWR=`4M7 zSf+8PdZ&VP9S3e^JM!%~VHOGI%F&nyOpef+eoWkhoz4NOXC8iPFP zU~$M(*0bldDCUCFkUTeP)Fyn6x8XK+Mw>H?d(xAUwmPBiz;Z$=oO~gn;Bf7flI=Sf z>N@En`ttPtd+$wu^;h4XK2XYQ)cnj8pXX~>TpM>~;|W6c3?;twjL#V#)faFbf?ZeM z*u;Gpxv{Vp4zAKu+G~|Zg+AWXcT0K1iZ;l1#PHX8`|Gk}`?xwwHh0z=yKybpW5>49 z(S|J(h1uuY-V$5+L~fpImN+6-Hb_j!c#NUI6crVXo?N1IW7BMpuOzVHQq2f>jSz_Iu6 zAoh;GLGWzER&}X4JBR@4Ko!6I*k=1t{L(v7{A0i&&hZ@&%O-mwI_9*)qS?8H^5DSq z81fkZ(pGz{KTJcm?a|=~(RVpRpSQ~vGCgh5=VFtP^Nkw_>;lG0pA(mJx3DyDQlWj0 z?P0l=bz0ksHl#vH6e*>Z%?H3@%f@V{O(mbQX_9dnUh$7dZ0<*UZjj&F+sXjRcwQ?F zR7R1?doJ=E#x;Z`z2*8e=f-)fGDw}e^cefFJPD?CX|NhR&L4|3E{)898wXGZ;3w1g z?XREU@}7KqB4tcKTh*sybDoR^W+f72uo>Nw&<=Z+kuHY|!;2W8TkimtgV1~D_oCvP z+px-~0a6`94|~VO$sV>lhc(+hfPHm1 zWxX25wMW9^f{2A-U&uh*Ues(aqWAen&jx4UEBsB8MaNpfzJAT|9Mtm+O0|Ps$WH6NRfsWOvhv{fTn5K*8&rRR|{`aQe z`nUgf`tZh$>FKLaPA|Ol;`F)Ce{TA@pZh!0rAwElySH!af;TtIRKwT@E(f#|HyF-o z0nJ5se5|okXYv*2ejv*xpWeE>1-#wya2VYNfb_T+PDX3*i>$G(d;GgEjg0lVJhbb6 zJXp;5_3P?Vi{;bn?zX#)5bRu^oqiRTx&;(1!cGOsebKWlqG$*DkqaXW&%V~!#kTaWeR6e~w=pqAp9%o*=-( z5LxIhmQK@scPb3=8C_n{7n{W4L%CSQ)7SPD zz^SpcVcY@Ae&ScWx{M6FF`d|K+=>uH|^E<*^^zzC#p#ER`+SjJn_~M((m!~^-ZoBPVZ^tDeDzDUc zbh!fnV7Q$QBl^e7oEF&WzI`A#&WF%D2D|klU-Q<;bzoU)8Vb2jo%bxz|C#a+CwhP)XDHv=TyY*ei z)j+>&DS^YG!Of(^#I~)2;1jkm97jcw#v;o%=ktxt-NvZhJL2XYZ>{h%Y4{PK>saL* z=;;?;ZKglZpFKBy|A#-E-hA^df1iLqb16L*)%SI*^V{Q}|LkYA2!3A1<(Z#F;+$Om zM^twkOVo!jwB2fK0ksG7%G!MO7orB$F_4_CoVMO0<~Y}J?8Lf5Sl~k)J2pW<+h#G}c%XV6hdJ*3NK92I?4$iG@W|>s z&vW3Iy1OsrQp>8|WL$`y7`HjHxx)=XdDBFN$#xRD zJ%!XY7J*qO*f?=gcaV{>rIX|zCFVBR)L~Vp$}1tXxxJ6UQiV|xVl%jifj813n~*jh zsyvg4VWy3;T%gX*7kS$r<&>{8No1s>e^0oj)SuBkINGPSwi8%bz-x}b z_v7dJCxcrEBP5Jo;`DRx_$f3bp6InzupMWoH1!u0NY z?@s^v|M)+qfAz2a)%4eY{nxGmuSw^#CS1ms&GJb*uk z;3w_cskc$M+F&pC8+|~Ojq@>wd=rQZfWD5)% z<$@Q;LAcF3kjf_ZF+IX=kTGM!#HucGmJmy3WrU-z`@97^MNWB(L(4{cp}~f2w&gfQ zrh%_24?dSZEx6b*G{$2ePH#Z6RVku3_SIjkGF`ioU$sVE% z%hvJj1#$=p$XTZeiQc(&yQjTv*L0Uka)Yh!xm?mKyMfz-wDQItxnnWMR{8zW1*7fq zx3|qoj$|)?g=72`uz}PpY5Ti+?P`5KliV2h7E;=cagYcL1l1IgLv=GN08H!3p=RDwe)t%NieUVwJ$XE#d zG1hpfFUE4qy2Fo052ziSQhx`nr<7NIZDC`c{;zBPU2ObD7U6{!gyv}lm6|Nr_vtc& z&;_LkZEZXtPGe)A4CnTGYT>rlzmFc*D=~Xtx~&~+Uvj%gm$xBTPA;EcWPxox9H%VCQ+ zb#hUCe&@G;clyh3|K)V)(nT+VbGMc1fczU1~hQkxys zMUrn)xeh!rAL7{?-=hNcV57c@!`14#9}hx0)THi9q1)U=+m4R8Baz%JTS7wip^dgG zyU1=+p+xpVQpRyIVDx)>V4V%U^lcWV)y5$tDY=d(@%vxdjQ6=}Grx6H45w|AXDdHD z82O!VV3F;l{%<+ZvRm3%2INOy`>~9hq)Y$O7K^={pE+msEHc!eb{=F$K=q+j?3VI3 zxJws**hJ{=UCmvZxARK?iH8LZbl&)=Q2lnx&6_uKlS{`l^V=28buWMF)6+B0JYyZ6 zDtjzR-rq8>%oCdD&OV{}^0Y{$yI{MSGeocRO{z^jT22s=Qn#&zobT~f^alj}Va-HO(2HrqW0Zeubh)$bHI)K?3jC#XSWg&iBDqCwx+ ze<#uR@ek=_PJ+%xegt#XNZU6b3)q!?Ze*mUkTOQ?Q$*7H?qq0utOL7!^MV_9vdtT2 z;`^!Z6L|*(wr2+ZrT_SK=v_SAA{e-Hj&Dx}PGkQ7dU$v|IOF0BI@}YS(B2X8*l1ZY zI*GZ+0#dLnJ6_uyV-?>Q^qp@*W8Dvw4<9&)l&uvci};{>oDBlbX9!R!d2RlAhZu6& z7wf<*P$oyqqp!rKyv-;Ny^<{s#kjVy)`bJiYV!x|A4DrXEC#2E16vh92+7aTB*S9H zZQeZUj;QELOIu|Y#7uev4h`B6VV@`VGiRqi{KG$-{^GCx za=LT-?sV?_d4F3pbwiAeZ_&PW`?fOor%!$6Q`1+!_SNYNpMP~abMEYPTNlqlW#n6LPR&dyHd(vakJW6OOxbmrjTl-UbP6pDiQ@$deojU&f(0(SF_ zuJ@<&XU~g8dq`wni8OK{8-4nS*d$}0#8h;n%L4IAr|TX4pAFnDgWsLJWA8B#-d>33 zxE(q>jw!2Fc@HFj#jWiwM^*dc?RZ}t81`R&9~B(O;Nu|LX~*tV?M5wH-TjQ52ueJ% z26@{!=*tS>x7;d?6f!=`L#7B%*s(w69}pe$A=p=8<$tcj=svPrdvm-lBq6id8`xb~ z6IZmN8Xe#0Gh*~Z9)4uL<5)$e<@(qKef-AOh%7_2^Zzn_`ePONLE9GY%O>ZaDA^OP zJylB9#z-A2DRZA}sPy=C=v{oGi{KG->M|IQKOj~(jh~IoUi(`+E|bx&$(*!m@Su&I zdHzA3e9>2EUnj-zfWX{rf=m-O{v#5)&!1-dP|~0FAwtYc(?;2vq>(T+Hdr`#D$@6lxVTS7f(hJhzdPN%ePkXtV))r3^mt;zlj2KPE=`v&UG^f8&*SCB41N*`vZ*H?AuMfo z2*^{D6U26bf_-JIV}qI|NnCm2Qsr4*^&yRb7xgS!Uw{4e=|BF*Kc4>PM?dtJ-(0+) z1;4-KO0sHK7XG^Y)?)aMbwBs%&rIL=);Fe?UwOqcJS{F4ZokAtIWY#Lp`Q-OqSN}j zx^Xl52<(?T$rXoD<{-6r$Jy<;V@Dg5QKzxeb*^M91#L63HJ&ZJ=x$+I(QPZ)g)X$t zV)p@n?jarXDnEm{1tLBxkS(MKCv_!t2}Y&CI^Isp=5cY&wm{8w-pC&ZWEhK>&#`VQ zzIOC$?i9NHQ%H7>yXe_t8yh^usAC>ZT|kziC@l@GbSan}UI;~;QxfI_gLSL`9WtaA{}r5Q`(*N;bMFmwtirVV|eO97{0TZ0hI%QLBsvp=DZsWoO8P)@`}A zQH-K1TV#?^3|LfX(pWyE+vKh8gJHDr0H^?#^I?&kVpAI@X!0{XasVyHtBZ(`CzX)f z5DbZRNt@PX81n)O*%J6Tz*fglSodr4RhrTDnWsqY(iW(g;PPmzZG<1iS;u>!#77&A zS*?=6wB;ikyd`wHAA{?@R(2G2BMUHR4w zMowAgAL&tGLgP!d#DDxd!Mk|CMR0Wr4bSK}faW}a;fF`X!hm4_;@f_=F;WI4OL;!I z`66HNBAED*QCZ~KqUD=T8HGaU=QzqnNYQb=e4i36KiZf9fzX`S#$rTCMQgqJ0$%l+ z^T*&&e53!9>hNH)O9f7=15P7jAkzWOzN*i?K~p;Oo7Na)jPP2bsZCieq>M!}F^9D` z_94dO>nA#_*$0ShUwEPGwpFSe6w?FW^EHppukob9GMZsg3Ag;K%!MBJATORfUsjOI z1>n1HzdK#K_JOWr&rE0W&4NyU{$i}N=ce=L&iS*kmoHy3&9Gf!0;FtMj`e_i%LG-O z8C`BEYlwJU+cwWS9YddKcYLnP)XNvQs^i7;7gV=1(~p1rqv;R-=s!$9`N%(ltZ^K0pH1sPMaV^ama#bt@VJ*$~V8Ul>=K_aS&>msr-Td+=EfJZD4WM9(*iy zbxB+2Pe9vH;v=hkGBy?yWJa6hH^2_)7)pEyu~4@5j#22NLS!AD$;1YY1zE|UE;%Q) z584KR&IYaNqihhHY6UK^HnO8uw^0zCo`Vx>=9ADt$&2;`7k;yjIi6#H-Igb-7nU)A z9a8Neb&9@tM|X~<58nS^`tZXKrgf!)TT1nC#|}L(V0&ic4OaZi=|%|P{$^> z%$OPo#F&fJVKg<`7-4-enuYdOY#Z0?yUK0cubz_s1h9?a5D@7)Edd?_?D_`FBJ8^L z;@D*EB$Fv)k#kJ`Q+^1|Q$(vKpeht*S!*WyuqgXuok?ulG)q-pu`1F3LLXqdFtWyW zAM=fNoBSZ_{a!cwF$9*n?9*+lC&PVcGxTq4VsDOL2@fj}B8AUGiuT}32zFiri0Zjc z`4X_5nlE2{{3Lh>r(XoqknX7xC%-{c_8D9ax*>lMv!5hGW*3r0nuQ+y&rOn$p)#n( z6OU++=lD6;lot)k7+WTY3`*-XEe2MT$swT1Yf;#+9sF(d4z)+*1$dP|BnLIE5Yc{B zg2MQ@=a@M~`xiR4F-FIwd|QZR{O`BF&&DC_lNs%QEMV799CKl;9UweyF#1 zOI?Dt!x*az7NKQMQ|AUIk{-IGVL)i?l-~f|wz|a3amT#GMdUm0zB~Qshd=gDn%zCR>o2(b+Sk5nEiaBV zNAW<}mgLkAU4}Z5CPv9~o|VlrXEi@EF7)5+K*3G3b4>0-^G6`d99{mfJ2t{d`x&6y zVD{E!`zNNP9o~phXO7u|vQhOO+xS7@5U{mJf3(}Ny2vhy2eA{=Njj&nNp)$(h$WtE z$775oL&{cM2Jm8Xp`8Y^blGn|J9Qrc{Q>-p?cOoYwjsdx$}V!A+lzl(93yYevnhXU z{6b<%yX`~x+wn{xdJDR&`Io%?Hm#MnIt$vr_u3)J%!PY+UelBeGxKa(6BB=2ccJIm zZoa;AB#=cH$BUxJp9$WFWf4pxtJS-OLOcaZ?>O{e^q^9D$Tl3F81(`UtK@uc*{cL` z@O>Z_4+{H6qzsiQIQocn+qv&Ix3eD<1+16nWR=Rl9deMAe3%x7TGxb}-Ez7Hhd|}LS zNNjPoiV7OM1Aw!V7rGAN9Pf7*$WwnUPWZT@)+?C0cUPyD`}d}cmoDa2N7e5K-~0ab z7k~Me(~o}g)9L;_J~Mp5-=OUq0E&S{3QvxXj*k50T3`RWzc{`2`B$f>o_fkd^o}mb z?ax(Q;-t;p-fXU1>XDmk$o374`wFoyvT5h^bab@{ur8crd~;AdThq?%L|$8ZE9kzk zTnLtJz-NB3ZVAEO%66SB+kC+)5gue?;}Ebl#;`@lT!ji~&{0Yb))2r9hoGYo^fWndHbf{TzTi6cdYM^EQpROZ)JS-t3N-z^3qE_HhsMC6G^s==Y1F>qmHDV z-=Krp<_+aNj<8p{F3Yo6CR+#IcvKca!!a52OE8ENft^4BF>5ZCFR;LB$y5jgo13Ws2M~_#KaFjzQ?9zk~J& zAK5+g!2qQ3RYCTD*vAeHw4g=u2ZA5UoPXT<2Tc_lU< zumwcfaKiz+9N>*5XS)3gma7zSF-t-Jwn4?11Q4pcCl}f9XD}g~wOo7x+Yr+>x{Qtd zFED?R9qTpr6Rs<3G|%e7%H{^6?y37;GDso+Xo0=9$v7{}{wP$yE|?1O^syg@+3qIq zL_1GDI5nG1`tc;m)R zKNY@n_l{}LKmU9!5^3w$;sW#n-yn^E;AHUA<&MoBm*N8hd!voh*=jA2JX0jUjm-7v zUDc1@?z?jNQjF<>nmSR>@BiQj(;xleA5L%Zo1$6-^JQV^_z5}3vI4k$`?h57`DyTH zKl|C~%U}8O^wKLY<=blKxwv8=4C!=xL!b>AHvIGp^>GX($Ho_G_&aIE&*@R%&awI& zacnQ2u?$R??#|dd1;%-Vyf2u_j_0EXG)Xm3-yRENdCU9wI235n6HrLLxItE(K;lIT zfKUGkEBRfF^*CM@I>)(=pp{JM*#PC{kF-t`SKHueMRSwMT(anNj@WV|hkS=n)+$%F zB-3XI_U-1C7tr=O>TS2iQm(k`YM*@yuB* zVx@j0*|*+)d-|In|9HB2LVWiFX+jRSrkqlvW$e@pNT)5}U zj#K}MhJeG^?_<^(%Kfx!A4WT^b6EPpv5oUk-0?az#*ENiC+UVHTIWxLQ^_Cle>@J? z=P=rfJ*sd>ogT-2kCS->prHTxIvaz;!HLUs#`-eOfNdd59#ZAqrfwgXOat3KYkN&4 zg`63x2nCmkXKOf4`BcwxN{E1Z0(gK%ycaPBT^K za<`TK{H@V0rRC$oJGZ5eEB`-!61)#PuS3)D#~m!)F~^APU~cuYeaOd(9ycEYgEBFz zXxsYt^@{5uP)?FefpQ;=&{yRGWykD4WHKn%ux7Fa#_W8cYlG`@`SFrZ@Zm)>lM=v0+1ia;@*-i*AS1%qN3GE!BSzgr z{k_5>ob-{RZITWb9V4oKBf4}#vKT&cwo1cDh~Zq1KWB+$Cv7qpNXPI7V~k)w?^OB#q{^T|AXm2{_&qoZ@u-FF3R~r z9iAFrL{i|G5Q}!CXU}=b z>5W}p(Nt`V8621)*}4+2Y_(e@3q+tcynV9Ej4r_Jh;dvsP>=u2F8lguLHt=RgduYh z>?GL@w&SD6#D1*257^Sl^9r+4Y?)0;Mw=Hg&CVGQ^=uZ|CHI-Nat ze)`t8e#tkheC#-Y1^7KUWDJf;VIBi*!n#{4E;kO z#;$+2$%vEu9zREYOkj6UOe>s5rXg9zfXAEFxMt0{tB+;p`BQoRI23gB#cNL@4WKl{ zurDUc(8&&E#@P0)0>|i#iwDthcYUy#kD0WqjbWGD=*Y8jvd6&MHIGq1tF2`Wlnot^ z)Tu=+Q-U3r+ZZCjf-nqxFe)D}f_E`I2~LBJdC)DkQ1$@%ZumnenXUa18F-O%XM#}_ zHpy0<$#A>qtE^u^<{Tv*`;~0#hb8e{=^U!vHD>_^;eQVt~35T5O(+_JlXXpOWF8T!ge z+U)=SAYQeID!7d|RauXL#wS@n{Mt0T1hF6DyPqUO|2Pj>+nEE4l~dt>U%L`(dm>qb zn=@(~{dr)%G192)@r{_r2skRkF87yMc9tYf~?jKfD0!Nb~WJvKrU#q`s{I^~vx@;VGtlO^B0I15l1%Z&|vjuj)&bv2`c^rHTOr+?p&7cG(l_S!xUSXku!ks+1W^CciZmK)H( z9-lRrjiBhaV#JCE`Z(7uu6D(rHs$lbSeCHdGKb*>4o`;t#Mj~CM|9d=f1Y;Pw0rzI z^e%Q5!6OdSwS!DU@3J2qFm7ijgE)yd14=p-~E7ajO@eslZF(CEwcgI?H90KUlZpH+Qy zt@^UmVU6gx8rHRu$d8!g8SM(_Y-JAtT`=l@(r91pd&IujxAl8i*q`jQrTAC531lj! zj%>#(jF_4GX&y^OZ*<(|@9RKeTemKcX@iSU`>`+al^IPU&!X6G8F125IkqF@g`8lU z`Bxs^I)>8%Gp*L~Zqe}{vcJ`fbVtnDgo7~fO*Sv8bC`x$ZKSkm=gvvSZNo+Tt9h6}gKi{^{iI$i)bb?)B1?QdIV%gwX+ZF_xli@E09+4Fvj;=T9Y zo!pHgH_D2oS%`4H^$6w~BBR+R8e@{R4?DWzrFHfKP^ryT?zQ;F1J3dLqnX=J6 z5j%1m@K?|F(bjAZm}r|T5* z)_}`BHqhPecX6_(~ zy2hpI!#c**vJJ*+wW8)f&$cRrO?z9!bELmG%hz9zp9Js2{5mw_W~ZM84=7=G5Ii8< z(L?+1E6;;7Ny~WfH%+K9pf1%8`X0N)>%q&P^1Mc6HlkeUDIFKf+0f-5;;w8Tu*g}0 zvJ(8bol2hp*$dI!5r@9;t*tz|WVs~GIfqz7^HX95KQh)!RH+jr?X}IXmtY^*0EiDO z70C+})Vd-iYn#eL8rvDTUWK_$_oS!6R(2_~Eq)B>;y(xyPpLvUNq_5OE)!2B4;aHC zP}eQ0cb9QxR7Qz&6$)s1Fpp8wQgU13r&4&9GL1~}3-0Tc?7}lzW)lG+ZD+Vx*M+l-W#6$sD9}M)sr^&8w$pji#$2v=3Ox?jeKefyg7V-Z)0Zw^^_OSy8YdUx zzw*n!Jbm%!zU&Km^f_j4+_)jREBP5J$L?DaxTd6B79IFLBVTFDvx=$eK$-ffKW^T< zEu+(P;o^B)=y?%KFcPz~sTXwGXJ){w`3jrVxyapyE;?^AMq;D*BN8j@4Lw#I5Bt<} zu`#A6qGj4gmD!Ira@QYrX5)p|eCbEY<)$N>e3fT%%k9FZBxez&tug~bGo9@^_X4xc zYiCFrz-b=F9DAR2Ll~@$&<@*B$zCEEtrvW zog~Yr)+7DIboc1~bad~ozm48so<}VD<86n0xn8~bpoQzrTQ{}%{a||Q%{Qkv-+Tiv zKF0XmK612`ZxHM6NHp?KK6!O|lyel zINPDcK+5FPUx#41vWXl+!O}5jA1;@llhJ<3V!IOQAGWo$=Y9+}H|RFnwHup0ZU#7p zqRsgT&NR^U+4IKEqeM){ABBzq%<+%B$~W9+6d_|r|7`-g^YDT7m5Py@vCxV=*lhUP z)CMCn7tz(Z&>HZx*%n3d9CwxRiQAahP6eMaEkoHtl?HRYO)MGHs;snak}hbOeP~_K z=?28A1g;mrs+6sjA8V1<9K|};BKI|KC|{DIB{tVlZRDA&bp@_hV(alDcpsj4@52wr zW8f3VJYeUpFA&6b5iB67<$6z zZ$8M8LL|iygg$ueuk z(GXsq0z_5`ZB8DN%F$D<{3T1CV$;`fEJg3U>$eA%8u)E(zw`zN{5Rs8oObPhBX7UR zjbrT?o1oj|q!^E@cVi`kSrY9$uHt5HBgbh0m=Kj9n`|H%CP#lJ+&t-&FgAlyLZ*Rj zXSCP9*&Wv?TRfvLj*kJKspA`v(aDn>#t=856jkPK`O#i^=-6ZHZ;yTuSf5l|N0rc1 zYWpjQ<~osVc`I;%y2Ruh*RH5YH_Omm#F|tc1D{iF@~N9gjypq(VYSJ5U8rCC;M(*j zfAYuEcfR*MTVNslr7wQLKb_?G)E?;ZB>3*V`+i!S*GZ`p(VWpjf!}VHH@|HH2Ohf4 zX$y_Y_L#r~?ZW4X0o3LNXr-J5gf?uJh!;pTXW-0ajN%wR^upK=js5*G(o{xVB(oq5 zc4kS@M!Wk_hW4O!*YVIM(A#eFQeJe5!9&%bd4BUS9%mbNq2W=7t)-&C3_=efZ(^>Gjv&(8Bk1EtoSV=*P3fhbiwEmiMQ7 znv3`nt*4)UdiuiWU!9(L_8FI1hw_9Z^0MJKF>cw;)l2+z8BdHIpo8g{3};g6MX>pG z6D4(NjP-9hyzZCH&8#Xqy16i8iKF`C06ezi&}sT4`SFIp3(ksD=NC+xv?$*>>WC%UG>-i7$Bv-ab? zwqtY)iMQgiqI5>JI6$xse{8fBzxh!%7Z;nlRGLhc#P6`6S-$20^m904EPR6mC1lWX zx#|ud8>nDZ{}e64Zh#LHYlJb|L0+572~1>&@>=87lkFaz;TJ; z=zXrGzVVaewex6m9Ful_1hQM&8pPdg=~y_wD(@o?g2Q(!`b)7Qqw^0j-an#bFT~2; zvx&n)M|&yM<$>{d5xk3?FUA@%cTS~`8Xma9j&0}zjhtnR=CX4KK)gJK;)JXNb{@7U zY5Rz)J8UuFppE`broPJ7z{iHa71jlvkV}^d+!uwGS}?a)Gw{K&Fbqb}Z97BqUhG0+ zBQNFL{a@2!ym+o>oq8%R(j5>lI+(#6G>JN1|526<%#&grU_D{vE@9e%g%bXLJ5ArF zpETN66)NxrEB-OC2;uIFd$4O;D$f$dix1_C!9}SxS} zWfEmPGr1z;E|#9>_`+DvZ5`l^G(;VG74FL*Ha-57aFMAi*DP)&h`x%>pS8R+u|ZNX zY<-*tE$`SJ&|;(Ovy{DG$&Eh4j?RLzp&;F6ij_tFSzR>yPx91}S28bNxZt^?=biMH zbj9QMskuhZ@poprc@px2N~t|6qFZ$tS1hpMTD=V9Q``k$o0jw9|c`^jHi$ z;U{IcuHVuE`OfsrGf(^YzjOEAbR=DD5R2L|(+cX~PbGp!A``|Iv@mxXd0mYr16_YSA4oYW*Pj2xupaYi6zX` zH^&q>bLO1ilDKv2rhkI%jW^zy-v8hO@x`0{$(}Ojv@y1P6OJ247tT#Dy!hhu=}&)Z zdiohHeiZ|6ThyhZK)unI9r@_b;a|CUMTbotgERWok@f8A?r4VlQs`J zmIgfZQ#WVbr%Ejw9>{fpv%4V1Ot>qVHVM+dDY2jZ37mfrP9KXXX4ea->5V@3V5?~j zw^QX?AA7#Ou(OgGY`2YW-`U1c2F(Xe1CWPe3WF>d{WVrGgy1sywd5j;*?f^&XonEl z!+fwWrUwQ3J;%1K(eEMqqi@Sso?ohCc#N&}IBr;eK#MpwXS89XZ4WlOu6xX$04&+sj4s)o&32=4fHa`3b&1RV zMe2tTb3|$slQ_<~uF}Px*Cwi*I39a$b1Ta_!b&r0mp0>g%hYq`@gjH+hDC51Y&>Z8 zB0^R8m?&HAb391M`sPoCL17&t)|wA#U~=sDEgw7A~rh4He!7hDU(;)vc%YTW;;gH z9MD2@a5j*nV|`d`ZFKwZL-)S}Qmn`wCw~YJqjM~V%{ z(&Bi>uKZGe*PYim`HU{6>NiRS>^;HfhPAN8j-%18Z>}*XxSgOWVY{F<{Ifs%v*}O& z3reUSEsLh<>#gsUVdr1a8V0!(eB>88+qmpV$o)sI-vr8Iazf8a_n=nq(G+o zkQk`{DS=Km?E|RoMfY*1#$X)EPQM-p>sEfr9Ei2})}h@Hu*XV+V|53)Emn0p23^0M z`U~NO?xz*D>0*JxAUiNuVgrz~hW+GFkA(%X%0Au>(%hko*V_s(6%!m*dOkT2|Ohb3Pc>S~WKo_poxSEf&W=2O$RbnINjhOVRM=&`UhIT+h&uW*vDVINbmahzia`%1{4Nb3=uLj*LLMZFGbE0!^HE?X>bBult z`;dbaD$41c8(nr>Z(+xo)i=RDXXJ+1{yO0Dx+Bims_j=Uh*cYSeG`0*H~#DgKdg~| z3K-EFK8&_i=lU!vzyua0Vw1+kCqv6e9Ff-hS$QvCC+EgoO$%Z;s8}DaGchn(=EQ0r zAAtO|prN{C=o(dv-_yr{(wROP~6w8n*ht;9RC zAAj<(KjQq>+i#8X8MDjfZTWobkN)WLfBWzLyUV-&cS~>PJCHK`+Sk5%`L$pBRoxK( z=H<&j|MTm@pYKCD1c7AgPn)Pe{9Z2A8kWIPy$Iy#l7R%9-5ix!=95<5Q!V?vBP|PJ z+ZIJ=dor%WXQJbhq?Qrs?A$Kb^Y%D&Jqs>wjE8IM`jPo6qkygk2NizyhoL|5O?>aJ zVf)*)cfWeP+mhMwp7_MB@Qf98@IRp!GI#^{xlx-7E2D*-rTgMZ)z-DL&V;@w3xlcT zj)wpn&s=OAy8(?6PTFkG&P3(OSn}Yzzu)`b_b$KlJHO+v1H5?iEl)#_EiWeVBbR(~ zg8$q7)h~bf^2@*SE0=G4{Tr9}-h0=ditw+~SDyG}?6?_yspHH#^@mScaIWniMF1mvnuLg=mV6n9&x`j3>d?b>qh^n=*O>l>uWjs6JS{N}b%*aUiX7OT z*qvwit}!{pTR@fo52EATgY}h%ecR*9)<1f9S_?ofpZM+jc?;dQ*#f&B0-$P9+p8SS zM=7f9d024F$ouPbHm~ae&n*IuRr_{4yxhdsaW=r&51M*RRc!AVi-fXq$A!ZFga)p` z@k-`I*FHgwbNMVFoV-ziQjCyT!BKYf-9Qa}U0`eN(rRBhU8ly=r(hj0^u_(LVdRkR zlYOF~?|u_PExKR(h1WO1M{Mr|pH8yS@>}{dU<>ZqSG=nQs|^mBz0r%5o(aJY4|7`yig%-V&*^g;n~1{*7Xb=$1=BsywZMMU(1ed>l#PD ziCb|STRa&3(Teejs%L~oa{FQ5b`je)^B;RIsUU4q`MZwU+6Y_B@Tb+TFGRc{JNRCq zYmsVR?7-(cqCXbx)i-CLYixcGWU5yesr1o3l$~!N@#D{K zDBC~BQ0&o5?i+=Qr9C&fydco;_T+fx7Faj6pX%aV7x(=C(ge{aU+VnA=RSA&NB{Vr zTz>a=|38<{f9^dTeN)0p_~642bW{Do<%?hZ{N>lb`OV9(=!W1If9aPmZ|i269}?n! z7xOML^X8gGq|5Y)wn`)&HCYher2DbeVx4GSkjV>s0)EUiNJ&-wT$@6P7eq4PK0C;IZWC-To!1UNG@JS^ z5;HhoGuR~N6|ncb$M->CGxF`w{?}usB6(;m`IT z>!O8s0n(MZ{l(0>x(4@6q-E4s`TAzM<4P!14t$#-0x`cr&t12taG*q*c4t1A?L{#0 zoqqQbAMEB04`{k;CfUA%YqTBk9$K=9lPj3?ePD&PKgvQlgb08c?VQJwO@)XXS#))d z?ehFx7-WTVUB0XV)`Q1Ifq0kM7lOn@FM2n|qL;6L$RFW_Xt>6~Ux5hs^aBsXii%y< z=3{`*x$P6`dId=7W4*gGT0=F$OFo}SYb^KRA;exi>TjHK8}@z%g5U}cfNUf;dlJG8RrH){UIRVr(|J@l&#OCoF|=0ds1|4 zuSsrpP|3D^asG^;p53~2TxwvOG-w%US&)yk<~yT_X{q@$EDil*OfrzJC1VsY4m^jf zBMwtb7Q4%$;jv&FKQ-lQ496C`*5ZBKhfP1c4(f+gw3c4fO@lAUG}l<;!i^~N&4m@~ zj_=1~>kBQGpX_nR$dDW3^nrZD`tT#(;eGS+?mN1Pb}jC$ zYnx*qP(&4C#5U`op)HvGI&zncvjAL+E&(yF|hVTnwGO^0B>)5k4X&Rlo`*P&( zq5@*M)>6|<2yMrqWaf7i(&q+$Qc2|5n3n0T<_Ywzqx5@a$Ch=Ps5W&y%FDR|Il?6i z-Pbo8pcCV)=I7v8J287M9*fgjs!N`e0s1y&&QwKkq}EG7E2dwdu2>VtobbMh%HU-T z3vJtZT?533VH^94(H8&Ajb+kPqt*DwO|+HP@nS{4u!^CZwk3~Z9P7R%zp~qb$ZYd? zoyY1m+<(P%VeXd?429tsJ^B*&AnO6Gj(2UGi~YMpU9Vcsb-?MAgJ(>O6eAV%3w?Rv zA#Xk~{x(TvVltl*e)IKB@D(0+6MO@Vd9SZ54EV=|YhQbbIr=rfEx2|V{0Y{<(!h;Y zzF9gOV%xE+*_-TQEnUSrwH-3ElnT<N7)^i<*))8lBB&D`h3~s;<$W<25A8V(jG~1(q|J zt2khPh>2jkP!xlOk6I@aM*_2-J+E>oGy$1q*LX9pIH-amH>0=wp2i!vhkj$TW3by!1-VGo-&;in`x&M}IS+;q zd*aC$@&Ll0NJxe*04OV7ZE>-1x9goaPP0d){{L)^V;<5tQTJYC;3SVRx>t26LuQCAFG_0_oKBNOeIwm9DPf~=1X~>}UurcEJYsY^MbM}$tryAU zK)jhcgjnHf>wj`WPfqQxo>22KP0h3kxcLHj|9G`!1mR0$Ly) zWpa8XRl{$BXFDlqYcuXkUfh)Q@`MkZU3h|$;@38JbMEybfX$ryZJ$`)rq5eo!S`?C zAH$Tuk!f;@6;_=;OKc1(n>43Rc@%L4Q@2}nBlj;G07inrE1)bX#JTH;TDQ;j1xH60 znrp9944T6~2x13)CTEr9%VvJ0TraX@GadLT%jE84O$dO*EAoqv==L4|if|9yK0%)K z=mFB!BW}!An;nKHCi9(X)~^&a%8#$GU-X*0Y^Srf<+0i+)G@_y<8BcF^?Y^9H>Awn zn`=AlcDi&Vy59I%YKxUi=Z)3C>sa2s0M)O1?V8}qRFtN6Q1iB#cLG8hxOwkREqm1L zBn7)7dt+yRQeLZ|ISFvK?)xQQ2%u8&SuD?5;yLe_)(d{O%l2cWbLAOc3B(m)UZv#p zn9Js0kRROxonoU^9IMMl$$FOfA3U;JjIz(=I6KU7tr5qWLUu>Gi=AML z?;lkcZx=jYRuh{wo@_7%esKmyrAW`DIwQBSomibBWJ#+N<&$8A%QNgjc9b8-5o4jaH}#f{(1%`I3yHo{BeocDcH)`@8tpwEaj^lj{B}Ul~Z0hWyZW^|NiECwRA`|r5 z0O?avqU8MP-asS#ZNzdD^RT3pV-ru-aHg((nPKLqEsxq0RaYpk zDcN_y|Ag?T4BQvAESefGTU2?xd+Ydr2Y<#v5nm%RzP|zq&7i_UQ7#2)}3V_ywK4-&wDPvM+)vMoH62>R9f# z?xbT+_F_8=BG&Y*vLz8GHCt-(BWK9gY3}N)3N?-aA*hzWyfRg9-xR^(zW$@>Kbam8 zk9z^dfiGuxIv;UGlvg~r0&2?}J4YD9w9l0c$?J38f0pw-yEb?thWiJ#KT%O#G+Inz zO3+czq`-ND)n$jnQ$n4er`bOiwxVBsw`nybHECNT#r>+wSA{31Kt z>eYR_e;mrw&l&yg+rO(MUERo5hTsB+iy^qu!!9MZ`wV<~R-X%KxttFTl5`%x5=!SaTX^uY^8ebWX!F7ci#DR+LMV#Td4PA zlR`@}CiOLH*Qn=|~Ng(8@)7xusi4FLF{QmE`K9ocr;wG(btp zknG$V%7Icn7-0iEANh2>3}zf?D-d&K>{#5ak9(ARB%fWKx*}3iQgG{d{jqqez1jP<|+%gdF^+Vg~L|?41u3D5%xFZA2 z>G0RG0JBwbapS5%IT=&JKnyfALr#nRs?`)_Un|%D3jbZ8+}_wWYvX7Is&Temkkz02 z)E60V(eeVJ=RNng46O9<7i07Gu)69&l6URU%%xvEC25h#qk^?*KILz>Z~MwVrO!6O z(=QwL)4pFk47eO+q^@9TU1JX@Nr?m(AZ&Y@1>n(B&RVfwV!{(i+uk`r4D=Cw?vdah6)iw>_kS4? zJR>1_*?~$vy@U)i!R~<=8cVm7lnP0|U3I^hvEnY9Y^UaL)h|zR z*)bIumt##g)4rwzlu~x36`C9GQP)?sl4+-S8f6tjZAY|#NoY(97*E0=z`a@pm>?wX z9@#5xk$>_UtNKw~H5N+lTb-|4Xds7yD64ddK{ExE3L)+Il3fHd0b90VpzT!>9K4b^ zzS!`jdzp*q*%%WSs!}=<>LtRk^ZPeo*Lic@{hVrhAWwmBloH349I%Aj0uq=;%Zg{( z*a|khI*4$muI`%(hk74hOYS zJ0jHfuaM0^Yn7Q*l;P3{lNz^Ma#k`j;ErJ5fbUg#kV7m0)Jn3WKNU%rwoS+dP!|bf z5r9`yLFZ2Mf%M>_t`w9gOjqHoTm!&v4AZD?@Xt(Cme z!MCDSc@>UxMP(rS3l)*kiW`nMj2!wB0le9n5zv+{209;ytjJl=r!dgR91pi9Y4 zM+PJrUAjl|^Hh*C+W}KN@?YEo$L2_#=3@~7YaWg;{;6|OaC_~UTcW$Yfzf|EZJ#T` z{GMVoPOhAWrTVuRtkdB!#ZFU4i2z~A`SPPq(m6~YhUp5xF_2?KV=|EWZ1s}9L7K7p zTqJfY#=78s{FU{@(fvkvQcSJu5wuh=?PEk)N__@He62e|pwxp)!|zrr0x>7|Er#p~ zdFKrkqhqwVY&zxvdZSyET0tbRF*~9f(;mTd9e*a^`B+E5-@RRKY}P7D?Hb!_(l`v3;{%9ajE zBG=dzSfZcK@7%Q~MmtTr;{ei<(ub~I1!%d|wWP9VNzp^#whPYlIbE*mq~kE7TQ%k> zzR>jYb}m+)%3OT(2y30AK32}*?9=YD(V(2M=ico36YFWcLDPt46Cnm?0y1lAWo%34 z&OFn3@kr10?+02AzQYdAca^0IyA;kRbgPS2x4yf)gKb(3V($FlNm)?APbc|CAP&T! z0mM+~NklTVj2{aiFOqx$4s_Iy2N7SEGMW=FS+4@NnQ23iq}_F-Cb($PRL;r z_HvY^u?n1}sJBBN_PFFg2j@Bcdv5&Fmoe@KS>A%avtLrny!Dvx$8hO+T6LBZ*of6KcsX-6bdsQYYwiS!77)hD>YtotI@zV4@ zH%=+&aRz>a`BWp^>&4P)VY%fCGq*&>ci0xf^q;-N3r$ z|NefaF2x;u3kPrzjqVBceO$ns>eX7|PG?SNg=@N-)6c*P2H9KO#+oWeJB+VvtM1{w z-NSj=szCz*Eh+`I#`sy($QO#Us@IzkB1ZJ0*)ppmaL-8T0_FI;jY`=la zO#$IcLB*<5nvb}Id1uts$4%1OPi zPJp6@nikL1!x$z=4|m_uW5$G<;WdR_`zR3=#Kn#F04!k$blTC9L*tIp!d$@LU<-BP zecf}dMay&#GLs(fpEgo&$l~5kxaBB>4&4~`5j5>ch%&-A7H-7!UmHkb9F^NA)0M6W z1M>#Hd0Z*{c{0bdUH;1k;+F+q1yW`%Jwboiq6ae@uGz(ywB@mhdr1mTlr0KBwTpQl zwN;tEk3F5bNqU+gIN1t>7nV zEobww65nzg#J-aWtE){x0?qWt>{6!b~JT0c{-8j~9TdoX!mBK_k}_ZgIV zi{V|ASKcZemRz^sKY+J? zTQ|kTw2YTa;CVK{CXSxnA9@rX&CaCr2mEx2Yu*d7Na~f(j;~f@i0fj%daI$@Y$oKM zXWKUG{fI>(>EPMW0E6)wk2bJZFVLx#ibd=JxTDKE}R94_^EoRUH^WRvTAz zrN|5Z>{fT1OFoZIj>t~lQQ(jbA6wAeNJ;3NMeEM*X&Rp zAH;1K;##hwMnWo$WTQt%?wfY*yC0@AjXC^?hTkYyg8fOEJf`>KJp^a>t0me=eqvmkL)cvE*!WS?$qgu`ih>( zd5`hf6TKsM*d)8r3Fqp4eg(?02cBCu*-{0VO%#++lFU=S50eF?U!fmh)TSzw>Mb6T z4aKJo!KkhReSHfbF88u~$?yY_2DKaJ$=a)5vp}bs7>=!C zXe62+aTp$i^z8GEl^Kk)r{ebh$Mzh69$?5IDL~L!1@_^EAeY6amw!Mus zdtA_#bKT(|WS2q8t&bQ zZmmUckv?QBa8#Le42PhBt;bXna6b+o0f21Fb=IPaP`^iXcKHF{4PUSPoy5G<0|8GK za8h(i#t5kOv_bk5bL@IQN1pU1M1YL=7(T5X4YCu=rphO`RnF=h^FXL!N*E8!G za{r^_;y}nBvOsU4cL+y4mzZJ|lm7N~%sRO@-?;}?zoEC{@2l=JZy29D>h=1>!-_kQ zDSqRS$*%U#?VtslDN()!nYSH3bfFE$OLK{5eV79~q1@83z$WS9U-DJrgUz3>Hiz4D zhFpGq)2B3dugrig54n8<#iO4d@!fqyz%-Yn`1y5H?CE@FQ`+Kmrxt7=kx9BIv06Yg z4Re}W`;-n={`4PP6%cvW>D9UZ3Kb+GP~!L6Deg`Dgc85oi?xDyRtKqKZzjPp4rk)y z|2ipqN*(F)uy?8>%_GBHjB-NTxRjkQ=_S}lfCuvMGo;KRx$rSZVKu86L-$(Ps_7KY z@zyiXS1tkGZEJd*DUODSxJ4fC{U=FNz*z6Nos31kb(8h5Ahwc&3v*0o5x8t_3P-{W z`VZ=f0^!$vB}tU|hjf8W28ofE0vD#&In|brv0cHX_ER@iyqbI`BEKNkOFO-sVI~2O zf}S#`gX`-(%}!qpE9+bsyq!gbJWL*BTbO0=zFJ03)@5uELi)B+-m#8RR%{ZT#|9Yx zNNN@XISazgC~)4XpmjM}%a3sfylcv7I~wH~j+fW@oL9?%CI=2E@q)~$b&~#j^kjg| zKp)Isay~W;JlfScb+xaKC~r9>vU@W5QbV1OP+>y6;;B`)e#Jds`Yz;{RA?{#+#}W+ z9*-UKe~rB9eJMb5x~T3{5ZV9BcO-`MpNB`M>S{+Y0I)nJ{ZHw~8zD$GOs+%AWaTS6 zwRPm_)B8JqS|zlgF)ct4n24%t^(Mk0_!B7%^#`zpye%=6A!n_WhI`ARDTK2O>&?~XUg9?J9twJzOMfdrC~RZMYh`8-Dh_I{umeXlQ-lyk z8Bb4BYFyvH&s!>evBRe{(ct*!+QT;I-N$d$Eq5_F%F1L6#;0M~?@CjT~AA$5wnN1RKs&gXv}E+gIc zxIjt{LtCJafqN0qMSjrQQ79+I(C^;q#OcA_uWPP*){>9q0SC($b#42P=o{QOXm0wK zY<$EFvb2TSqZLD%sB#I2h|(z9hy4OLw|@a#;U_z)GDh^;L4G>i>0#SY4ygL`cZX#n zQDmNu?&A(M+Tv|O4s!dLkn=;&+cwpeo;!e>8tIv@oqJmrPz?DEGMK%XdS`NJ%{7GQ zpeO!q_NKr3UZXo~-EQGu!^m}Sa5G26eYw_AbuA|;!x#Tnnl!D{FTkOne(hTf<~66T zH&8cQo9~a(lnlC6|3m(A4HOru3E!w>C57j=I-mlSjs=8D2cXL)BqkV0#$n z6(88>X;CBuAiqFw=yoPn7H#=Ti*~42(CvQKMB$bwyuT5JbL)b+^&bV}s7nEx!AG<1 zb?rZ_S@DynqbcJf`CemfPhk7qN{NqL)+B&?#mx$PZvjB@Ov5b!u1OqM)C;CpCFs5{ z{9_8~*KlHQfy-4tE6Rp0#DjS3+Zsfipi_o1 z+YqcH!i}g6-H7xmO3ekJ}aB5ljeWy+rg!A-Y z3-|!&^%R}I|8`ql`gx@#AoLMhS*7P0thlZ*`_U_u=%XCLzOQRxzRI_}$J@TT&&94M zhw*orbQx*m`Cs-Jz27A7$3wk{0NM;~T~~1LdjQo?`k-Cu9^zqtD8Kl^l8u_1@jD4j zmbnzZ^<;N-3v+sB=*W=%T_Pk)!D(b%pKTgB_|>v9cWx8Rg1g{;RSUau#qlcfRMo|Uz42p>^*Gt{nQ z71uaV>O8I(tIVO%eYv4>K#;}*A9DH2>SkF8CPzhpnm9BwkMDiGPGfM_8=eQh3 z^}7e1e{wfvgc%p+_o{f3(?K#aQjrp*uh=89BSkK-S-Kgz(pAl0R{4>_f>dNjZ;pgY z8|aLa?)@k-E;M{2XFGFUNH%E->xs^PXz7IxSN4(fqge=QseT~w zi8Sx?kz9-|e+A_#Tg%=>o<|+D!( zfcMJ8z~ctU-tD;}DeSBAvzDRj^0V}I%rcjdnYFN?E30)?f1In;-5UDs*mi1(!U~ks zhPTzwDVV^uu^MBf05T~F7b$NIOBIK--M?bjJp8WWnJ0~ir|x0QsND#%VX`mAAAL-w zt+)2(7#N#d(AUQz4bATUT0U^v98MZU+?x~71J=n#J?T) z>Vji?>{_S$bpSdc{F|zGHS_B;_kum&cE3|U)S9En_t?J%d6oChZG|5gwM+k=XN%ro zR07x>Jo{u`=MPbJD^OR`eA2A(@~2W$&&FE|o0<_MTqw4GTvsgLgxw|$A?n9ZBnsa~X1CwC&+XP=x?|Mj z8zKp)m9WUb zOHaPHXj(3@dh%XDPhE^4V=|LtZRXBM;-p5<<(^G+UGD9-4Owy+Ek{iP^kG5S5L{Q{qxeT>VVd;Q|yM$F+`x z{u`%op7r48>o8pTO1I*<^0R4XdTW>XPsS^Q_wT0qH1o7?U5SlCScSzS8MGJT@}V#Z z5f_In8;J-`U~ddNzJRmVUj*}g@-xO~u9N9Pp1fQFS45h!3!y+(PUOZ=7-CuWceCDz z-$Bs=kg~5U1tf0h(trDYr+tXqH*D=^;{bhcU9c3DXo%v}09=c220JWrQg;w7ep}Sr8*g&3h(p2&Yao!x76Rfn_@Y<)k(AT>(>v57k zHB{Z~HPBPSCRV3k{=mjI8#!Yw{rk;wLXnLBVZ}V-$0;A?6+sefed2Id-ra+c#Fxa# zZ__#?$7}%d=4i0dKOC+M|yRr~WalWMBVSD~Vu9j>wqhld_&Gdf+iEp?lnykiEEy{SvXB9>=C-{zz>ErnOpR=4)skiJ%TvG^=2%;D+h zH(gEtjZy!zNKL^tH;`7?9-CCCzVz#j_q?*gUhl$XtNX2{*;^Y~{&}^$`AFvGji1jt zS=4^1+h)9D?h0P_e7z;`1nvASe#q7BdOVw5)$KPPN%Bkcja6N%oA3y*_pW!*(EoZ) z(5+ACkaD`))zEJN@xp5PU-?~grE6(orxNF~^%QS?6|M5_*zIy>gk;0J^~&QJ|J(UH zEdh|`Caeb^eG#6nC9J>oat^xsc&+kWg`2rnk^LLykR2uk4nw)ogn`+`J4ZR256*=S zi#6yDD)YW8n;e(Dw61K}S@F6Hb9Tqt4rPz-<}wnf@O7*7aGCo?45?vEp8*@hraa2n ztnlm2FUk=0oSzrS{leRMY%?cC@^hJ0tX16~4KRC!YNjRts*JUM0KBZLc;z&H?i4c# zIP(9^w_H)|eg^`deOZLzMcfQX6=hjSiO0TbLgL?E4D-7c$~N+jEnT(sY)Vz|w5lY$ zK}WJcuiCZi9+p($7{*^@O?#ATGj+-FpT4BB&+7%{h*@Tq6MG%bUPSwPF_KDvXS&Hy zvMx31lsowZNFE(KRea=LKQq)Ip&+BUoB=S@hECj%_dFUJ9vDEow(R)cAf6s7(EIfU zT&aneJ$60>!#3dDfMDV9=i6@2VSj%1k8pbb0l98|P330tl(ISqW2rs;{rJB^_p!|P zSGK;U`ttmUX$;~j+uxIR)7n%sv9dyPKHCo!C0bU1t55#`3;WnxfJ?dct_Vuf_Pscs zXIMR;!!?{3phR`q0j(!B6e~voSf7U!`9-}$)|)bJsJE<@x(i>42?<2 z$^TRO&sNhgic+1DJt!|6m{%;z-f)2hF(F;yoFs#F|Y?e(C);l=BX+Dqns{Gga+Aqd2 zJ2hWSwPpn0nq(HedMt#DyGgm?%nP?#_A~2YXqaBtonUfOlbWl!{}pvTcktkfj6ioO zuih}mzv2$?=XDDlmt97Lqk4L{qKgD=Z7W^_^hBW@_;2si`H?Ucf6jG2x3`Squi+*s z70Sbf0Oc43v+Y{&xv`a0CrtX&T#JdE)i2T<5~cs1c;Ueh0tKf|{$?G(oWKHOj`vkP zrb6Q%noSk0yCgt{`?iJy=&(xdi{m}B z3BB4-#t0{s++`%Exd|z`)DqxF?N{Tls6w~iVXfl&X?ZU%5i^LFeFtQ$f>&j~I(ykjy#AP4 zexTwx8hpIy!?$%I`nK$_^HjTpd&>ANR70+|nbPl*CPcd7;bK$z+}x6*?uHC$4vjaZ zZjZG35>Wu?0RAEkNjsFpR9kj8eRXZ|Lvvr<$af)RF@aw9<;9y-wY3*M!Rc-I*_{N< zA5vz^pa%prf`X<3y5}MZ_mTvzeMn|ICuV7;eS|W>uZx-~1pe(t+$}b)=Uo9Q`8z4v zi5CKWq!4r4is{-GB6+kjk4J^yW7xkuYG$0pq}h^|IHBwOFBWbcspQt$$v-rB$W7^4 zRhxh9Awp?q0n|fdr&#dN^|ZNoAh}nefgHca>FqgC_QhHYzQG3hV)a+L`N0yKT(`~Z zY@R00YuIGS2DdaVA3>=T1R_q!?R3{)%N9NidfFZ##O3nUAF?FqPt8B1i&D;rbNh*9 zL6g#tn@#Xt2l!ZW)Vb~vnVv9S#}F~a{zB`=oLs5^lo3;J&18D2t3*TU>}cI3&{#3+ zuiAG|vsW`>!rl)6?oqJ)_#3B2QUNXAm4w{SzpNu)YSj8a8@b^h*Em=W@_wp~U3!w{ z?wKf6x;)!zrQ7&;o);hDeDl~x;mg)o^}*};gt*h{=}UtFbMRW3?|J_;(WU#Ym>jHe zql!_3rrmJ`FJ`o&1a%|CPrVNrE#VpZXX-&zbJ?n5@118Wt7Em-vw(@d;eWC@lt`+Z zX+o1vUN3(PDyU1W)*M?ubb~Lw)5zPmtdf47RL{MI<|L@*twqhi-J+Mm`*qAbblRzL&R@<{P*ge?LfVs*#!hZ3?Dsd@zMQ!K|qdGUmo)(p{aiK4fB=L z%PGL`DOg-+o96buUdp(%NzKK%OO2MP!8?3fz8&vI?H!fZ6zFosKo2(NpmkN zZ}Q+6$8@@Y^#Dtlb$XU}XP#%?^YPZGI)_T#NAIqS5Uujbg>K{){Oc)2*vufvN+i41 z4?X=WinH3L`-%l2>(lYuE$eyFXuGQ8&U)~LsgK-x{B*mrJ`jAA!9#HowM+&flVDIS zM%R{;yIr|h(J%bcQR%gBo~oB^boInL?FX4J1g&Bg$ctLQR`RJB{jv`yN4Z4PRtTYZ zD2+gkz;A*7REb(vzajpyaLGJV$q+*PzFoB1Y@MWyn!D)PN%W=eVp_=rX<9UNo)5nJ zpCqpHzr}d^av=iPNIt+&%xL0w)eR^~E~oYP0#7nV%*@w&;vvnX-6kru<~DBXYeUq^ z+L_K#82;6P%iW3wB2IKnAxj!~d}7m(y_&Hp4OR!VtciXHB!<|kf|=fr+y%QJ@mKH4 zEBqv<{l(BI7zBA8NygZ&!T1Mty>m(5aSIwx;MMQ!%%9!7@oU|AT9y5vM3Ed3o7_)o zbxHT+BBNU?*1DM&bRZ{cM^QDS*lzPjK~UVz;RI$iDV>`=g+YpWBaW1%1^w;T;&x8a z*G=fvi%EP=$D{RYFqVoZYR9+AD~W;$dEz&y^82!GVTE=s4tkdWfXb>E$pY2#%#>d1 zn{Mehtr>qr_>4HRJ@vo+`pW&);e8SvzxYM0LlGPaaqc zIho91*WcCh=7#6k$Nu*$810}-o8D1pJ(le#P0|kyZay7svegrYzV;QL+(OlCS~j5E zINjIEC<-mebBV9jq?R3j>5kR1_j}Cfi&$EIj+4I`Kf8hG0i*&_dTzkITc%}hQksQ6 zE`NeWZpnT?bI*Z{(0Ti`*r~=^=)Ir}G?g*-<$VpN5(ByVqtooA>B`$_+qLwD>2WNq ze*~S=)b1j|+L04{}`EKKC~K0aH4Srg~M{)y@>kIqKmu$|L=T zT!{9t@M~}9B?ek`9JdsMOs~VC`qlAz5rq^pU1{^NAdipo)!+V^$_M{=HTST2+vDEt z_i<{1{5ei4F5Ts(ht0fYebK+nQZ?(cb(74__)PjT0LBjol%@~MoipaR3v3AN18FD& zdBHjv|B1_X`@0>iPctog5MirvCEM>`Zfkon#Sgtzux=y@%}S)gh&#vA?b# ztFHjl=*|Z9+l6N#e)}5IpFj_9E$`Y9{}Y5(ZTZQG-KxVH;zX%R>I!@*$H>v*t*kIf zpUhz5T}f_V$orpj3dPa-3w=yvQz5_r(&$Ks$*zp-#>q)2p3G0H@;g+SmcAClZ{)&2 zdC55ceV-OZ1XO|Nj#V(!-T&>#zhmZCnD^)|-ovnmR|=1GW=PCN`)kP2`g_>k?6Rv; z3?TpH^4fq;!@u!Aw2HJ_U&l=$&L#(F$7K}5WNGM;qd!tV05j()Lr8Fl6gRH)T?jZJ z0H_pbJ$V9pM)PUrZak0YE>F--qw-t<5x%C6v6IJ8#e+C|im^|at(uUim{EIm5n>^N} z+?u@EK#OZE*CGlEC2K~5i+8#*0e4!NeN4ZF$ntv#6G;=+|@Yq#`4ylfk_ zY54bjKsmsfLDudxmxeWtZQ+&1C9uv-w1Y*QL~a7|!+zvDq_%0DKwEY9QhT27wSg?b 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

VBJN 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

5mFQ_{f`o_24W1Jhdt^Lp7#Cv*9b)$!) zg^%tA)fZFg));>lou4yK^^MjZ)wXLoI^?J3MO!;O64t^E8X3(2{1dZ}sDTK`$8;@%u?piD%$T{xu(uGS>%LU8401yC_zssX&I4p4KVwr@ zTX4v!3p*$uSG~mbzpSB_mBL_bGsfVe^E&13K>lY4u;I-+7LxPGy@>(S;_tU*NE4BGJj+$o0}uxjG)hal`X~8n3?vJAT$oobw~d z@8O%2E+YaXqhqQ(?-~cq8tgf=&lo#*h)UP~AKdZFfBPT*^Zndt;`}w!nZR!WTd&06 z$^QlD=J5%*;{Q~gA8{6!VCpieO9YGlF6_PV2_3_+oBBMLqAzdcTqz(U?OsVI zAN$(!j4qa#Zk}j?fKCU(%=jE*tD=xlam}>B0J+HM1^+J0I}-x0YSD z*7v-Lk>B(d;XhWz{Mkr|I6b*Wep@eMI7m8!UNNyl43EgPV~NMb!aBAWxZclm&|b@; z&hww%?sgd;u?!inYhS58V(dHu>_^s`Z|B^*SoW{u9pA29I5odP)^Ftz{iCp-;(4A; zv7^Ep6My>h_b=+T6YxEIW^kSll=)j4e6MgOL>% zwQNRzn=6U%Yb$zEwpRP9IcLop#(bFTUpu7>65Dwv&cVodVW^|ogOljO`8O{3IL@kj zbi}dD;^;c&+ZffbZ4Je#!Ll&33Pw%$JQ5eNU*OXBpf=`L1k1R1<>GxqjctTdtuhkx zGX-SMF5VcDxYYL&UpW5MZ2E4r!WEkQfXRzj7Jd@F$7j zoRfFSJH8&nCt7N`jG+!U`EC8C)}Mm>pAj0<#~uHfOZ=|!@5D3Dsd3ljNm_PGx4r$l zWU@Qo=8+wiG>6cGH`siOQA1JxV|RSh?HGk?vt4XC+6KAWr5RvbxeiV7#8do7*1$PJ z+W)GZBbsoB_gEtNgw)YJv5a?pI|eZaP;Mi;t?O5q*qGPD*>!-Y7GCuFn`hSL9E|}) zq~;N+Z8Qc-%%QFxf_-Eo9q7~LMX^wx!^8p6mR5hM0>#E=&&T0yOFs_O5JKd{8ovNp zAV>?&KDZDSUmGL#2wEVz%?l2(cvV%a|52agv_^KN72g$5p!@v5N~3D&fSS8 zR92vSdOvNRc*c8L!#i%<8Us4pBbxdD_rHJla^}-a=1Yuybp;yPfn7!>olCXNwLc>i zJM0X)e>_0g8HS;(#_Z@88Pk!$eChlNXCXnpZlxJu@T-ng zPEP5Oi{)JP3483Wc|=D1NI8srkUy6XC1K_2@i#d!%~Mx|2=X;f>(T;ewyi_Xn+zjW zuJlMceskoRLPr#t38`q|qUS(Mnh~nQC)e;BoWJRmr*!LaujV}UuG zCh<)kujv;$u7xw!8{Wylo0uEBK*j?vb$jk6)-&eTZ9HQYjfu+Um_4oDGL%3H^xhM;OMI>~e1-9(<}i-zFMqw!dJY%P z`8WOHzru>qIeCsFK&MvwNA3grUj7~*eb}J!Z?Q7|udwx=tB3gy{b^s=oV6NIm3>z0 z9D&B7tJI^-a6JF4sO?OL2i47wT^wj)!n?Vq*(cUWFT(et7+6}=mN@R0{;C(9$sglp zc#ro9RB9^@ezTLjb5R#s-#b_*SSva;t2OWP8_5eS-*%2O%qL7uF&pFIπ{GR4z_ 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 z + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/apps/mobile/assets/branding/recursor_logo_light.svg b/apps/mobile/assets/branding/recursor_logo_light.svg new file mode 100644 index 0000000..e32b9f3 --- /dev/null +++ b/apps/mobile/assets/branding/recursor_logo_light.svg @@ -0,0 +1,21 @@ + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file From 57bce6992577090d1e93a4c2404a930e241f0a5d Mon Sep 17 00:00:00 2001 From: MasuRii Date: Fri, 20 Mar 2026 12:54:54 +0800 Subject: [PATCH 13/22] refactor(mobile): replace auth flow with startup sequence Remove legacy auth module and replace with streamlined startup flow. Delete unused auth screens, providers, and OAuth implementation. Add startup controller with bridge connection validation. - Remove apps/mobile/lib/core/auth/* module - Remove apps/mobile/lib/features/auth/* screens - Add startup feature with bridge setup and splash screens - Update wireframes from 01-auth to 01-startup --- apps/mobile/lib/core/auth/auth_provider.dart | 117 -------- .../mobile/lib/core/auth/auth_repository.dart | 49 ---- apps/mobile/lib/core/auth/auth_state.dart | 17 -- .../lib/core/auth/auth_state.freezed.dart | 255 ------------------ apps/mobile/lib/core/auth/github_oauth.dart | 98 ------- apps/mobile/lib/core/auth/token_storage.dart | 29 -- .../lib/core/providers/auth_provider.dart | 2 - .../presentation/screens/login_screen.dart | 151 ----------- .../presentation/screens/splash_screen.dart | 65 ----- .../presentation/widgets/auth_button.dart | 73 ----- .../domain/bridge_startup_controller.dart | 91 +++++++ .../screens/bridge_setup_screen.dart | 200 ++++++++++---- .../presentation/screens/splash_screen.dart | 95 +++++++ docs/wireframes/01-auth.md | 125 --------- docs/wireframes/01-startup.md | 73 +++++ 15 files changed, 410 insertions(+), 1030 deletions(-) delete mode 100644 apps/mobile/lib/core/auth/auth_provider.dart delete mode 100644 apps/mobile/lib/core/auth/auth_repository.dart delete mode 100644 apps/mobile/lib/core/auth/auth_state.dart delete mode 100644 apps/mobile/lib/core/auth/auth_state.freezed.dart delete mode 100644 apps/mobile/lib/core/auth/github_oauth.dart delete mode 100644 apps/mobile/lib/core/auth/token_storage.dart delete mode 100644 apps/mobile/lib/core/providers/auth_provider.dart delete mode 100644 apps/mobile/lib/features/auth/presentation/screens/login_screen.dart delete mode 100644 apps/mobile/lib/features/auth/presentation/screens/splash_screen.dart delete mode 100644 apps/mobile/lib/features/auth/presentation/widgets/auth_button.dart create mode 100644 apps/mobile/lib/features/startup/domain/bridge_startup_controller.dart rename apps/mobile/lib/features/{auth => startup}/presentation/screens/bridge_setup_screen.dart (53%) create mode 100644 apps/mobile/lib/features/startup/presentation/screens/splash_screen.dart delete mode 100644 docs/wireframes/01-auth.md create mode 100644 docs/wireframes/01-startup.md diff --git a/apps/mobile/lib/core/auth/auth_provider.dart b/apps/mobile/lib/core/auth/auth_provider.dart deleted file mode 100644 index 01c713f..0000000 --- a/apps/mobile/lib/core/auth/auth_provider.dart +++ /dev/null @@ -1,117 +0,0 @@ -import 'package:flutter_riverpod/flutter_riverpod.dart'; -import 'package:flutter_secure_storage/flutter_secure_storage.dart'; - -import 'auth_repository.dart'; -import 'auth_state.dart'; -import 'github_oauth.dart'; -import 'token_storage.dart'; - -// --------------------------------------------------------------------------- -// Infrastructure providers -// --------------------------------------------------------------------------- - -final _secureStorageProvider = Provider((ref) { - return const FlutterSecureStorage(); -}); - -final _tokenStorageProvider = Provider((ref) { - return TokenStorage(ref.read(_secureStorageProvider)); -}); - -final _gitHubOAuthProvider = Provider((ref) { - return const GitHubOAuth(); -}); - -// --------------------------------------------------------------------------- -// Repository provider -// --------------------------------------------------------------------------- - -final authRepositoryProvider = Provider((ref) { - return AuthRepository( - tokenStorage: ref.read(_tokenStorageProvider), - gitHubOAuth: ref.read(_gitHubOAuthProvider), - ); -}); - -// --------------------------------------------------------------------------- -// AuthStateNotifier -// --------------------------------------------------------------------------- - -class AuthStateNotifier extends StateNotifier { - AuthStateNotifier(this._repository) : super(const AuthState()); - - final AuthRepository _repository; - - Future restoreSession() async { - state = state.copyWith(status: AuthStatus.loading); - try { - final authenticated = await _repository.isAuthenticated(); - if (authenticated) { - final token = await _repository.getStoredToken(); - state = state.copyWith( - status: AuthStatus.authenticated, - accessToken: token, - tokenType: 'pat', - ); - } else { - state = state.copyWith(status: AuthStatus.unauthenticated); - } - } catch (e) { - state = state.copyWith( - status: AuthStatus.error, - errorMessage: e.toString(), - ); - } - } - - Future signInWithOAuth(String code) async { - state = state.copyWith(status: AuthStatus.loading, errorMessage: null); - try { - await _repository.signInWithOAuth(code); - final token = await _repository.getStoredToken(); - state = state.copyWith( - status: AuthStatus.authenticated, - accessToken: token, - tokenType: 'oauth', - ); - } catch (e) { - state = state.copyWith( - status: AuthStatus.error, - errorMessage: e.toString(), - ); - } - } - - Future signInWithPAT(String token) async { - state = state.copyWith(status: AuthStatus.loading, errorMessage: null); - try { - final profile = await _repository.signInWithPAT(token); - state = state.copyWith( - status: AuthStatus.authenticated, - accessToken: token, - username: profile['login'], - avatarUrl: profile['avatar_url'], - tokenType: 'pat', - ); - } catch (e) { - state = state.copyWith( - status: AuthStatus.error, - errorMessage: e.toString(), - ); - } - } - - Future signOut() async { - await _repository.signOut(); - state = const AuthState(status: AuthStatus.unauthenticated); - } -} - -// --------------------------------------------------------------------------- -// AuthState provider -// --------------------------------------------------------------------------- - -final authStateProvider = - StateNotifierProvider((ref) { - return AuthStateNotifier(ref.read(authRepositoryProvider)); -}); diff --git a/apps/mobile/lib/core/auth/auth_repository.dart b/apps/mobile/lib/core/auth/auth_repository.dart deleted file mode 100644 index 49c367d..0000000 --- a/apps/mobile/lib/core/auth/auth_repository.dart +++ /dev/null @@ -1,49 +0,0 @@ -import 'token_storage.dart'; -import 'github_oauth.dart'; - -/// Repository layer for authentication operations. -/// Coordinates between [TokenStorage] and [GitHubOAuth]. -class AuthRepository { - const AuthRepository({ - required TokenStorage tokenStorage, - required GitHubOAuth gitHubOAuth, - }) : _storage = tokenStorage, - _oauth = gitHubOAuth; - - final TokenStorage _storage; - final GitHubOAuth _oauth; - - /// Exchange an OAuth code for a token and persist it. - Future signInWithOAuth(String code) async { - final token = await _oauth.handleCallback(code); - await _storage.saveToken(kAuthToken, token); - await _storage.saveToken(kRefreshToken, ''); // refresh not used for PAT - } - - /// Validate and persist a GitHub Personal Access Token. - Future> signInWithPAT(String token) async { - final valid = await _oauth.validatePAT(token); - if (!valid) { - throw Exception('Invalid Personal Access Token'); - } - await _storage.saveToken(kAuthToken, token); - final profile = await _oauth.fetchUserProfile(token); - return profile; - } - - /// Remove all stored tokens. - Future signOut() async { - await _storage.clearAll(); - } - - /// Return the stored auth token (or null if not signed in). - Future getStoredToken() async { - return _storage.getToken(kAuthToken); - } - - /// Returns true if a non-empty auth token is present in storage. - Future isAuthenticated() async { - final token = await getStoredToken(); - return token != null && token.isNotEmpty; - } -} diff --git a/apps/mobile/lib/core/auth/auth_state.dart b/apps/mobile/lib/core/auth/auth_state.dart deleted file mode 100644 index 5855b00..0000000 --- a/apps/mobile/lib/core/auth/auth_state.dart +++ /dev/null @@ -1,17 +0,0 @@ -import 'package:freezed_annotation/freezed_annotation.dart'; - -part 'auth_state.freezed.dart'; - -enum AuthStatus { unauthenticated, authenticated, loading, error } - -@freezed -class AuthState with _$AuthState { - const factory AuthState({ - @Default(AuthStatus.unauthenticated) AuthStatus status, - String? accessToken, - String? username, - String? avatarUrl, - String? tokenType, // "oauth" | "pat" - String? errorMessage, - }) = _AuthState; -} diff --git a/apps/mobile/lib/core/auth/auth_state.freezed.dart b/apps/mobile/lib/core/auth/auth_state.freezed.dart deleted file mode 100644 index d209782..0000000 --- a/apps/mobile/lib/core/auth/auth_state.freezed.dart +++ /dev/null @@ -1,255 +0,0 @@ -// coverage:ignore-file -// GENERATED CODE - DO NOT MODIFY BY HAND -// ignore_for_file: type=lint -// ignore_for_file: unused_element, deprecated_member_use, deprecated_member_use_from_same_package, use_function_type_syntax_for_parameters, unnecessary_const, avoid_init_to_null, invalid_override_different_default_values_named, prefer_expression_function_bodies, annotate_overrides, invalid_annotation_target, unnecessary_question_mark - -part of 'auth_state.dart'; - -// ************************************************************************** -// FreezedGenerator -// ************************************************************************** - -T _$identity(T value) => value; - -final _privateConstructorUsedError = UnsupportedError( - 'It seems like you constructed your class using `MyClass._()`. This constructor is only meant to be used by freezed and you are not supposed to need it nor use it.\nPlease check the documentation here for more information: https://github.com/rrousselGit/freezed#adding-getters-and-methods-to-our-models'); - -/// @nodoc -mixin _$AuthState { - AuthStatus get status => throw _privateConstructorUsedError; - String? get accessToken => throw _privateConstructorUsedError; - String? get username => throw _privateConstructorUsedError; - String? get avatarUrl => throw _privateConstructorUsedError; - String? get tokenType => - throw _privateConstructorUsedError; // "oauth" | "pat" - String? get errorMessage => throw _privateConstructorUsedError; - - /// Create a copy of AuthState - /// with the given fields replaced by the non-null parameter values. - @JsonKey(includeFromJson: false, includeToJson: false) - $AuthStateCopyWith get copyWith => - throw _privateConstructorUsedError; -} - -/// @nodoc -abstract class $AuthStateCopyWith<$Res> { - factory $AuthStateCopyWith(AuthState value, $Res Function(AuthState) then) = - _$AuthStateCopyWithImpl<$Res, AuthState>; - @useResult - $Res call( - {AuthStatus status, - String? accessToken, - String? username, - String? avatarUrl, - String? tokenType, - String? errorMessage}); -} - -/// @nodoc -class _$AuthStateCopyWithImpl<$Res, $Val extends AuthState> - implements $AuthStateCopyWith<$Res> { - _$AuthStateCopyWithImpl(this._value, this._then); - - // ignore: unused_field - final $Val _value; - // ignore: unused_field - final $Res Function($Val) _then; - - /// Create a copy of AuthState - /// with the given fields replaced by the non-null parameter values. - @pragma('vm:prefer-inline') - @override - $Res call({ - Object? status = null, - Object? accessToken = freezed, - Object? username = freezed, - Object? avatarUrl = freezed, - Object? tokenType = freezed, - Object? errorMessage = freezed, - }) { - return _then(_value.copyWith( - status: null == status - ? _value.status - : status // ignore: cast_nullable_to_non_nullable - as AuthStatus, - accessToken: freezed == accessToken - ? _value.accessToken - : accessToken // ignore: cast_nullable_to_non_nullable - as String?, - username: freezed == username - ? _value.username - : username // ignore: cast_nullable_to_non_nullable - as String?, - avatarUrl: freezed == avatarUrl - ? _value.avatarUrl - : avatarUrl // ignore: cast_nullable_to_non_nullable - as String?, - tokenType: freezed == tokenType - ? _value.tokenType - : tokenType // ignore: cast_nullable_to_non_nullable - as String?, - errorMessage: freezed == errorMessage - ? _value.errorMessage - : errorMessage // ignore: cast_nullable_to_non_nullable - as String?, - ) as $Val); - } -} - -/// @nodoc -abstract class _$$AuthStateImplCopyWith<$Res> - implements $AuthStateCopyWith<$Res> { - factory _$$AuthStateImplCopyWith( - _$AuthStateImpl value, $Res Function(_$AuthStateImpl) then) = - __$$AuthStateImplCopyWithImpl<$Res>; - @override - @useResult - $Res call( - {AuthStatus status, - String? accessToken, - String? username, - String? avatarUrl, - String? tokenType, - String? errorMessage}); -} - -/// @nodoc -class __$$AuthStateImplCopyWithImpl<$Res> - extends _$AuthStateCopyWithImpl<$Res, _$AuthStateImpl> - implements _$$AuthStateImplCopyWith<$Res> { - __$$AuthStateImplCopyWithImpl( - _$AuthStateImpl _value, $Res Function(_$AuthStateImpl) _then) - : super(_value, _then); - - /// Create a copy of AuthState - /// with the given fields replaced by the non-null parameter values. - @pragma('vm:prefer-inline') - @override - $Res call({ - Object? status = null, - Object? accessToken = freezed, - Object? username = freezed, - Object? avatarUrl = freezed, - Object? tokenType = freezed, - Object? errorMessage = freezed, - }) { - return _then(_$AuthStateImpl( - status: null == status - ? _value.status - : status // ignore: cast_nullable_to_non_nullable - as AuthStatus, - accessToken: freezed == accessToken - ? _value.accessToken - : accessToken // ignore: cast_nullable_to_non_nullable - as String?, - username: freezed == username - ? _value.username - : username // ignore: cast_nullable_to_non_nullable - as String?, - avatarUrl: freezed == avatarUrl - ? _value.avatarUrl - : avatarUrl // ignore: cast_nullable_to_non_nullable - as String?, - tokenType: freezed == tokenType - ? _value.tokenType - : tokenType // ignore: cast_nullable_to_non_nullable - as String?, - errorMessage: freezed == errorMessage - ? _value.errorMessage - : errorMessage // ignore: cast_nullable_to_non_nullable - as String?, - )); - } -} - -/// @nodoc - -class _$AuthStateImpl implements _AuthState { - const _$AuthStateImpl( - {this.status = AuthStatus.unauthenticated, - this.accessToken, - this.username, - this.avatarUrl, - this.tokenType, - this.errorMessage}); - - @override - @JsonKey() - final AuthStatus status; - @override - final String? accessToken; - @override - final String? username; - @override - final String? avatarUrl; - @override - final String? tokenType; -// "oauth" | "pat" - @override - final String? errorMessage; - - @override - String toString() { - return 'AuthState(status: $status, accessToken: $accessToken, username: $username, avatarUrl: $avatarUrl, tokenType: $tokenType, errorMessage: $errorMessage)'; - } - - @override - bool operator ==(Object other) { - return identical(this, other) || - (other.runtimeType == runtimeType && - other is _$AuthStateImpl && - (identical(other.status, status) || other.status == status) && - (identical(other.accessToken, accessToken) || - other.accessToken == accessToken) && - (identical(other.username, username) || - other.username == username) && - (identical(other.avatarUrl, avatarUrl) || - other.avatarUrl == avatarUrl) && - (identical(other.tokenType, tokenType) || - other.tokenType == tokenType) && - (identical(other.errorMessage, errorMessage) || - other.errorMessage == errorMessage)); - } - - @override - int get hashCode => Object.hash(runtimeType, status, accessToken, username, - avatarUrl, tokenType, errorMessage); - - /// Create a copy of AuthState - /// with the given fields replaced by the non-null parameter values. - @JsonKey(includeFromJson: false, includeToJson: false) - @override - @pragma('vm:prefer-inline') - _$$AuthStateImplCopyWith<_$AuthStateImpl> get copyWith => - __$$AuthStateImplCopyWithImpl<_$AuthStateImpl>(this, _$identity); -} - -abstract class _AuthState implements AuthState { - const factory _AuthState( - {final AuthStatus status, - final String? accessToken, - final String? username, - final String? avatarUrl, - final String? tokenType, - final String? errorMessage}) = _$AuthStateImpl; - - @override - AuthStatus get status; - @override - String? get accessToken; - @override - String? get username; - @override - String? get avatarUrl; - @override - String? get tokenType; // "oauth" | "pat" - @override - String? get errorMessage; - - /// Create a copy of AuthState - /// with the given fields replaced by the non-null parameter values. - @override - @JsonKey(includeFromJson: false, includeToJson: false) - _$$AuthStateImplCopyWith<_$AuthStateImpl> get copyWith => - throw _privateConstructorUsedError; -} diff --git a/apps/mobile/lib/core/auth/github_oauth.dart b/apps/mobile/lib/core/auth/github_oauth.dart deleted file mode 100644 index 2c0295e..0000000 --- a/apps/mobile/lib/core/auth/github_oauth.dart +++ /dev/null @@ -1,98 +0,0 @@ -import 'dart:convert'; -import 'package:http/http.dart' as http; - -// --------------------------------------------------------------------------- -// IMPORTANT: OAuth exchange requires the client secret, which must NEVER be -// embedded in the mobile app binary. A proper production implementation routes -// the code→token exchange through a server-side endpoint that holds the secret. -// This class documents the flow; the `handleCallback` method is a placeholder -// that highlights this constraint. -// --------------------------------------------------------------------------- - -// Replace with your actual GitHub OAuth App credentials. -// The client secret MUST be stored server-side only. -const String _kGitHubClientId = 'YOUR_GITHUB_CLIENT_ID'; -const String _kRedirectUri = 'recursor://auth/callback'; - -/// Handles GitHub OAuth login and Personal Access Token (PAT) validation. -class GitHubOAuth { - const GitHubOAuth(); - - /// Returns the GitHub Authorization URL to open in a WebView. - /// - /// After the user authorizes, GitHub redirects to [_kRedirectUri] with a - /// `?code=` parameter. Pass that code to [handleCallback]. - String startOAuthFlow() { - final params = Uri(queryParameters: { - 'client_id': _kGitHubClientId, - 'redirect_uri': _kRedirectUri, - 'scope': 'read:user repo', - 'state': DateTime.now().millisecondsSinceEpoch.toString(), - }).query; - - return 'https://github.com/login/oauth/authorize?$params'; - } - - /// Exchange the OAuth [code] for an access token. - /// - /// NOTE: This call requires the client secret. In production, proxy the - /// exchange through a first-party backend endpoint (e.g. POST /auth/github). - /// The implementation below is intentionally left as a commented-out stub. - Future handleCallback(String code) async { - // TODO(server-side): Route this through a backend endpoint that holds the - // client secret. Direct exchange from the mobile client is insecure. - // - // Example server-side call: - // POST https://your-backend.example.com/auth/github/callback - // Body: { "code": code } - // Response: { "access_token": "gho_xxx" } - throw UnimplementedError( - 'OAuth code exchange must be performed server-side to protect the ' - 'client secret. Implement a backend endpoint that exchanges the code ' - 'and returns the access token to the mobile client.', - ); - } - - /// Validate a GitHub Personal Access Token against the GitHub API. - /// - /// Returns `true` if the token is valid (i.e. the `/user` endpoint responds - /// with HTTP 200). - Future validatePAT(String token) async { - try { - final response = await http.get( - Uri.parse('https://api.github.com/user'), - headers: { - 'Authorization': 'Bearer $token', - 'Accept': 'application/vnd.github+json', - 'X-GitHub-Api-Version': '2022-11-28', - }, - ); - return response.statusCode == 200; - } catch (_) { - return false; - } - } - - /// Fetch the authenticated user's profile using a validated token. - /// Returns a map with `login` and `avatar_url` fields. - Future> fetchUserProfile(String token) async { - final response = await http.get( - Uri.parse('https://api.github.com/user'), - headers: { - 'Authorization': 'Bearer $token', - 'Accept': 'application/vnd.github+json', - 'X-GitHub-Api-Version': '2022-11-28', - }, - ); - - if (response.statusCode != 200) { - throw Exception('GitHub API error: ${response.statusCode}'); - } - - final body = jsonDecode(response.body) as Map; - return { - 'login': body['login'] as String? ?? '', - 'avatar_url': body['avatar_url'] as String? ?? '', - }; - } -} diff --git a/apps/mobile/lib/core/auth/token_storage.dart b/apps/mobile/lib/core/auth/token_storage.dart deleted file mode 100644 index 5d8136e..0000000 --- a/apps/mobile/lib/core/auth/token_storage.dart +++ /dev/null @@ -1,29 +0,0 @@ -import 'package:flutter_secure_storage/flutter_secure_storage.dart'; - -const String kAuthToken = 'auth_token'; -const String kRefreshToken = 'refresh_token'; -const String kBridgeToken = 'bridge_token'; - -/// Secure key-value storage for authentication tokens. -/// Backed by [FlutterSecureStorage] (Keychain on iOS, Keystore on Android). -class TokenStorage { - const TokenStorage(this._storage); - - final FlutterSecureStorage _storage; - - Future saveToken(String key, String value) async { - await _storage.write(key: key, value: value); - } - - Future getToken(String key) async { - return _storage.read(key: key); - } - - Future deleteToken(String key) async { - await _storage.delete(key: key); - } - - Future clearAll() async { - await _storage.deleteAll(); - } -} diff --git a/apps/mobile/lib/core/providers/auth_provider.dart b/apps/mobile/lib/core/providers/auth_provider.dart deleted file mode 100644 index 6e50723..0000000 --- a/apps/mobile/lib/core/providers/auth_provider.dart +++ /dev/null @@ -1,2 +0,0 @@ -// Re-export auth providers from core/auth -export '../auth/auth_provider.dart'; diff --git a/apps/mobile/lib/features/auth/presentation/screens/login_screen.dart b/apps/mobile/lib/features/auth/presentation/screens/login_screen.dart deleted file mode 100644 index 06281ea..0000000 --- a/apps/mobile/lib/features/auth/presentation/screens/login_screen.dart +++ /dev/null @@ -1,151 +0,0 @@ -import 'package:flutter/material.dart'; -import 'package:flutter_riverpod/flutter_riverpod.dart'; -import 'package:go_router/go_router.dart'; - -import '../../../../core/providers/auth_provider.dart'; -import '../../../../core/auth/auth_state.dart'; -import '../widgets/auth_button.dart'; - -class LoginScreen extends ConsumerStatefulWidget { - const LoginScreen({super.key}); - - @override - ConsumerState createState() => _LoginScreenState(); -} - -class _LoginScreenState extends ConsumerState { - final _patController = TextEditingController(); - bool _showPat = false; - bool _patMode = false; - - @override - void dispose() { - _patController.dispose(); - super.dispose(); - } - - Future _signInWithGithub() async { - // OAuth flow: start flow to get auth URL, then exchange code. - // For now sign in with empty code to trigger the OAuth redirect flow. - await ref.read(authStateProvider.notifier).signInWithOAuth(''); - } - - Future _signInWithPat() async { - final pat = _patController.text.trim(); - if (pat.isEmpty) return; - await ref.read(authStateProvider.notifier).signInWithPAT(pat); - } - - @override - Widget build(BuildContext context) { - final authState = ref.watch(authStateProvider); - - ref.listen(authStateProvider, (_, next) { - if (next.status == AuthStatus.authenticated && context.mounted) { - context.go('/home'); - } - }); - - final isLoading = authState.status == AuthStatus.loading; - - return Scaffold( - backgroundColor: const Color(0xFF1E1E1E), - body: SafeArea( - child: Padding( - padding: const EdgeInsets.symmetric(horizontal: 32), - child: Column( - mainAxisAlignment: MainAxisAlignment.center, - crossAxisAlignment: CrossAxisAlignment.stretch, - children: [ - Image.asset( - 'assets/branding/ReCursor_Darklogo.png', - height: 80, - fit: BoxFit.contain, - ), - const SizedBox(height: 48), - const Text( - 'Welcome to ReCursor', - textAlign: TextAlign.center, - style: TextStyle( - color: Colors.white, - fontSize: 24, - fontWeight: FontWeight.bold, - ), - ), - const SizedBox(height: 8), - const Text( - 'Sign in to connect your AI coding agents', - textAlign: TextAlign.center, - style: TextStyle(color: Color(0xFF9CDCFE), fontSize: 14), - ), - const SizedBox(height: 40), - if (!_patMode) ...[ - AuthButton( - label: 'Sign in with GitHub', - icon: Icons.code, - onPressed: isLoading ? null : _signInWithGithub, - isLoading: isLoading, - ), - const SizedBox(height: 16), - TextButton( - onPressed: () => setState(() => _patMode = true), - child: const Text( - 'Use Personal Access Token', - style: TextStyle(color: Color(0xFF4EC9B0)), - ), - ), - ] else ...[ - TextField( - controller: _patController, - obscureText: !_showPat, - style: const TextStyle(color: Colors.white), - decoration: InputDecoration( - labelText: 'Personal Access Token', - labelStyle: const TextStyle(color: Color(0xFF9CDCFE)), - filled: true, - fillColor: const Color(0xFF252526), - border: OutlineInputBorder( - borderRadius: BorderRadius.circular(8), - borderSide: BorderSide.none, - ), - suffixIcon: IconButton( - icon: Icon( - _showPat ? Icons.visibility_off : Icons.visibility, - color: const Color(0xFF9CDCFE), - ), - onPressed: () => setState(() => _showPat = !_showPat), - ), - ), - ), - const SizedBox(height: 16), - AuthButton( - label: 'Sign In', - icon: Icons.login, - onPressed: isLoading ? null : _signInWithPat, - isLoading: isLoading, - ), - const SizedBox(height: 8), - TextButton( - onPressed: () => setState(() => _patMode = false), - child: const Text( - 'Back', - style: TextStyle(color: Color(0xFF9CDCFE)), - ), - ), - ], - if (authState.status == AuthStatus.error) - Padding( - padding: const EdgeInsets.only(top: 16), - child: Text( - authState.errorMessage ?? 'An error occurred', - textAlign: TextAlign.center, - style: const TextStyle(color: Colors.redAccent), - ), - ), - ], - ), - ), - ), - ); - } -} diff --git a/apps/mobile/lib/features/auth/presentation/screens/splash_screen.dart b/apps/mobile/lib/features/auth/presentation/screens/splash_screen.dart deleted file mode 100644 index 63f702f..0000000 --- a/apps/mobile/lib/features/auth/presentation/screens/splash_screen.dart +++ /dev/null @@ -1,65 +0,0 @@ -import 'package:flutter/material.dart'; -import 'package:flutter_riverpod/flutter_riverpod.dart'; -import 'package:go_router/go_router.dart'; - -import '../../../../core/providers/auth_provider.dart'; -import '../../../../core/auth/auth_state.dart'; - -class SplashScreen extends ConsumerStatefulWidget { - const SplashScreen({super.key}); - - @override - ConsumerState createState() => _SplashScreenState(); -} - -class _SplashScreenState extends ConsumerState - with SingleTickerProviderStateMixin { - late AnimationController _controller; - late Animation _opacity; - - @override - void initState() { - super.initState(); - _controller = AnimationController( - vsync: this, - duration: const Duration(milliseconds: 900), - ); - _opacity = CurvedAnimation(parent: _controller, curve: Curves.easeIn); - _controller.forward(); - _checkAuth(); - } - - Future _checkAuth() async { - await Future.delayed(const Duration(milliseconds: 1200)); - if (!mounted) return; - final authState = ref.read(authStateProvider); - if (authState.status == AuthStatus.authenticated) { - context.go('/home'); - } else { - context.go('/login'); - } - } - - @override - void dispose() { - _controller.dispose(); - super.dispose(); - } - - @override - Widget build(BuildContext context) { - return Scaffold( - backgroundColor: const Color(0xFF1E1E1E), - body: Center( - child: FadeTransition( - opacity: _opacity, - child: Image.asset( - 'assets/branding/ReCursor_Darklogo.png', - width: 200, - fit: BoxFit.contain, - ), - ), - ), - ); - } -} diff --git a/apps/mobile/lib/features/auth/presentation/widgets/auth_button.dart b/apps/mobile/lib/features/auth/presentation/widgets/auth_button.dart deleted file mode 100644 index 16f940a..0000000 --- a/apps/mobile/lib/features/auth/presentation/widgets/auth_button.dart +++ /dev/null @@ -1,73 +0,0 @@ -import 'package:flutter/material.dart'; - -class AuthButton extends StatelessWidget { - final String label; - final IconData icon; - final VoidCallback? onPressed; - final bool isLoading; - - const AuthButton({ - super.key, - required this.label, - required this.icon, - this.onPressed, - this.isLoading = false, - }); - - @override - Widget build(BuildContext context) { - return DecoratedBox( - decoration: BoxDecoration( - gradient: const LinearGradient( - colors: [Color(0xFF569CD6), Color(0xFF4EC9B0)], - begin: Alignment.centerLeft, - end: Alignment.centerRight, - ), - borderRadius: BorderRadius.circular(8), - boxShadow: [ - BoxShadow( - color: const Color(0xFF569CD6).withOpacity(0.3), - blurRadius: 8, - offset: const Offset(0, 4), - ), - ], - ), - child: Material( - color: Colors.transparent, - child: InkWell( - onTap: onPressed, - borderRadius: BorderRadius.circular(8), - child: Padding( - padding: const EdgeInsets.symmetric(vertical: 16, horizontal: 24), - child: Row( - mainAxisAlignment: MainAxisAlignment.center, - children: [ - if (isLoading) - const SizedBox( - height: 20, - width: 20, - child: CircularProgressIndicator( - strokeWidth: 2, - color: Colors.white, - ), - ) - else ...[ - Icon(icon, color: Colors.white, size: 20), - const SizedBox(width: 12), - Text( - label, - style: const TextStyle( - color: Colors.white, - fontSize: 16, - fontWeight: FontWeight.w600, - ), - ), - ], - ], - ), - ), - ), - ), - ); - } -} diff --git a/apps/mobile/lib/features/startup/domain/bridge_startup_controller.dart b/apps/mobile/lib/features/startup/domain/bridge_startup_controller.dart new file mode 100644 index 0000000..da99a40 --- /dev/null +++ b/apps/mobile/lib/features/startup/domain/bridge_startup_controller.dart @@ -0,0 +1,91 @@ +import 'package:flutter_riverpod/flutter_riverpod.dart'; + +import '../../../../core/network/bridge_connection_validator.dart'; +import '../../../../core/network/connection_state.dart'; +import '../../../../core/network/websocket_service.dart'; +import '../../../../core/providers/preferences_provider.dart'; +import '../../../../core/providers/token_storage_provider.dart'; +import '../../../../core/providers/websocket_provider.dart'; +import '../../../../core/storage/preferences.dart'; +import '../../../../core/storage/secure_token_storage.dart'; + +final bridgeStartupControllerProvider = + Provider((ref) { + return BridgeStartupController( + preferences: ref.read(appPreferencesProvider), + tokenStorage: ref.read(tokenStorageProvider), + webSocketService: ref.read(webSocketServiceProvider), + ); +}); + +final bridgeStartupErrorProvider = StateProvider((ref) => null); + +enum AppStartupDestination { bridgeSetup, home } + +class AppStartupResult { + const AppStartupResult._({required this.destination, this.message}); + + const AppStartupResult.bridgeSetup({String? message}) + : this._( + destination: AppStartupDestination.bridgeSetup, + message: message, + ); + + const AppStartupResult.home() + : this._(destination: AppStartupDestination.home); + + final AppStartupDestination destination; + final String? message; +} + +class BridgeStartupController { + BridgeStartupController({ + required AppPreferences preferences, + required SecureTokenStorage tokenStorage, + required WebSocketService webSocketService, + }) : _preferences = preferences, + _tokenStorage = tokenStorage, + _webSocketService = webSocketService; + + final AppPreferences _preferences; + final SecureTokenStorage _tokenStorage; + final WebSocketService _webSocketService; + + Future restore() async { + final savedUrl = _preferences.getBridgeUrl()?.trim(); + final savedToken = await _tokenStorage.getToken(kBridgeToken); + final normalizedToken = savedToken?.trim(); + + if (savedUrl == null || + savedUrl.isEmpty || + normalizedToken == null || + normalizedToken.isEmpty) { + return const AppStartupResult.bridgeSetup(); + } + + // Validate saved credentials before attempting connection + final validation = BridgeConnectionValidator.validate( + url: savedUrl, + token: normalizedToken, + ); + if (!validation.isValid) { + return AppStartupResult.bridgeSetup( + message: + 'Invalid saved bridge configuration: ${validation.errorMessage}', + ); + } + + if (_webSocketService.currentStatus == ConnectionStatus.connected) { + return const AppStartupResult.home(); + } + + try { + await _webSocketService.connect(url: savedUrl, token: normalizedToken); + return const AppStartupResult.home(); + } catch (error) { + return AppStartupResult.bridgeSetup( + message: 'Unable to reconnect to the saved bridge. $error', + ); + } + } +} diff --git a/apps/mobile/lib/features/auth/presentation/screens/bridge_setup_screen.dart b/apps/mobile/lib/features/startup/presentation/screens/bridge_setup_screen.dart similarity index 53% rename from apps/mobile/lib/features/auth/presentation/screens/bridge_setup_screen.dart rename to apps/mobile/lib/features/startup/presentation/screens/bridge_setup_screen.dart index 499f2c3..5cf1172 100644 --- a/apps/mobile/lib/features/auth/presentation/screens/bridge_setup_screen.dart +++ b/apps/mobile/lib/features/startup/presentation/screens/bridge_setup_screen.dart @@ -1,9 +1,16 @@ +import 'dart:async'; + import 'package:flutter/material.dart'; import 'package:flutter_riverpod/flutter_riverpod.dart'; import 'package:go_router/go_router.dart'; import 'package:mobile_scanner/mobile_scanner.dart'; +import '../../../../core/network/bridge_connection_validator.dart'; import '../../../../core/providers/bridge_provider.dart'; +import '../../../../core/providers/preferences_provider.dart'; +import '../../../../core/providers/token_storage_provider.dart'; +import '../../../../core/storage/secure_token_storage.dart'; +import '../../domain/bridge_startup_controller.dart'; class BridgeSetupScreen extends ConsumerStatefulWidget { const BridgeSetupScreen({super.key}); @@ -14,9 +21,9 @@ class BridgeSetupScreen extends ConsumerStatefulWidget { class _BridgeSetupScreenState extends ConsumerState with SingleTickerProviderStateMixin { - late TabController _tabController; - final _urlController = TextEditingController(); - final _tokenController = TextEditingController(); + late final TabController _tabController; + final TextEditingController _urlController = TextEditingController(); + final TextEditingController _tokenController = TextEditingController(); bool _connecting = false; String? _error; bool _scanned = false; @@ -24,7 +31,34 @@ class _BridgeSetupScreenState extends ConsumerState @override void initState() { super.initState(); - _tabController = TabController(length: 2, vsync: this); + _tabController = TabController(length: 2, vsync: this, initialIndex: 1); + unawaited(_loadSavedBridgeConfig()); + } + + Future _loadSavedBridgeConfig() async { + final preferences = ref.read(appPreferencesProvider); + final storage = ref.read(tokenStorageProvider); + final savedUrl = preferences.getBridgeUrl(); + final savedToken = await storage.getToken(kBridgeToken); + final startupError = ref.read(bridgeStartupErrorProvider); + + if (!mounted) { + return; + } + + setState(() { + if (savedUrl != null && savedUrl.isNotEmpty) { + _urlController.text = savedUrl; + } + if (savedToken != null && savedToken.isNotEmpty) { + _tokenController.text = savedToken; + } + if (startupError != null && startupError.isNotEmpty) { + _error = startupError; + } + }); + + ref.read(bridgeStartupErrorProvider.notifier).state = null; } @override @@ -36,53 +70,112 @@ class _BridgeSetupScreenState extends ConsumerState } void _onQrDetect(BarcodeCapture capture) { - if (_scanned) return; + if (_scanned) { + return; + } + final raw = capture.barcodes.firstOrNull?.rawValue; - if (raw == null) return; - // Expected format: recursor://connect?url=wss://...&token=... + if (raw == null) { + return; + } + final uri = Uri.tryParse(raw); - if (uri != null) { - final url = uri.queryParameters['url'] ?? ''; - final token = uri.queryParameters['token'] ?? ''; - if (url.isNotEmpty) { - setState(() { - _scanned = true; - _urlController.text = url; - _tokenController.text = token; - }); - _tabController.animateTo(1); - } + if (uri == null) { + _setError('QR code did not contain a valid bridge pairing URI.'); + return; + } + + final url = uri.queryParameters['url'] ?? ''; + final token = uri.queryParameters['token'] ?? ''; + final validation = BridgeConnectionValidator.validate( + url: url, + token: token, + ); + + if (!validation.isValid) { + _setError(validation.errorMessage!); + return; } + + setState(() { + _scanned = true; + _error = null; + _urlController.text = url; + _tokenController.text = token; + }); + _tabController.animateTo(1); + } + + void _setError(String message) { + setState(() { + _error = message; + }); } Future _connect() async { final url = _urlController.text.trim(); final token = _tokenController.text.trim(); - if (url.isEmpty) { - setState(() => _error = 'Bridge URL is required'); + final validation = BridgeConnectionValidator.validate( + url: url, + token: token, + ); + + if (!validation.isValid) { + _setError(validation.errorMessage!); return; } + setState(() { _connecting = true; _error = null; }); + try { await ref.read(bridgeProvider.notifier).connect(url, token); - if (mounted) context.go('/home/chat'); - } catch (e) { - setState(() => _error = e.toString()); + await ref.read(appPreferencesProvider).setBridgeUrl(url); + await ref.read(tokenStorageProvider).saveToken(kBridgeToken, token); + ref.read(bridgeStartupErrorProvider.notifier).state = null; + if (mounted) { + context.go('/home/chat'); + } + } catch (error) { + _setError(error.toString()); } finally { - if (mounted) setState(() => _connecting = false); + if (mounted) { + setState(() { + _connecting = false; + }); + } } } + Widget _buildTabBody() { + return AnimatedBuilder( + animation: _tabController.animation ?? _tabController, + builder: (context, _) { + final currentIndex = _tabController.index; + if (currentIndex == 0) { + return _QrTab(onDetect: _onQrDetect); + } + return _ManualTab( + urlController: _urlController, + tokenController: _tokenController, + connecting: _connecting, + error: _error, + onConnect: _connect, + ); + }, + ); + } + @override Widget build(BuildContext context) { return Scaffold( + key: const Key('bridgeSetupScreen'), backgroundColor: const Color(0xFF1E1E1E), appBar: AppBar( backgroundColor: const Color(0xFF252526), - title: const Text('Connect Bridge'), + title: const Text('Bridge Setup'), bottom: TabBar( controller: _tabController, indicatorColor: const Color(0xFF569CD6), @@ -94,27 +187,16 @@ class _BridgeSetupScreenState extends ConsumerState ], ), ), - body: TabBarView( - controller: _tabController, - children: [ - _QrTab(onDetect: _onQrDetect), - _ManualTab( - urlController: _urlController, - tokenController: _tokenController, - connecting: _connecting, - error: _error, - onConnect: _connect, - ), - ], - ), + body: _buildTabBody(), ); } } class _QrTab extends StatelessWidget { - final void Function(BarcodeCapture) onDetect; const _QrTab({required this.onDetect}); + final void Function(BarcodeCapture) onDetect; + @override Widget build(BuildContext context) { return Column( @@ -128,7 +210,8 @@ class _QrTab extends StatelessWidget { const Padding( padding: EdgeInsets.all(16), child: Text( - 'Point the camera at the QR code shown in your bridge server', + 'Scan a QR code that contains your private wss:// bridge URL and ' + 'bridge pairing token.', textAlign: TextAlign.center, style: TextStyle(color: Color(0xFF9CDCFE)), ), @@ -139,12 +222,6 @@ class _QrTab extends StatelessWidget { } class _ManualTab extends StatelessWidget { - final TextEditingController urlController; - final TextEditingController tokenController; - final bool connecting; - final String? error; - final VoidCallback onConnect; - const _ManualTab({ required this.urlController, required this.tokenController, @@ -153,6 +230,12 @@ class _ManualTab extends StatelessWidget { required this.onConnect, }); + final TextEditingController urlController; + final TextEditingController tokenController; + final bool connecting; + final String? error; + final VoidCallback onConnect; + @override Widget build(BuildContext context) { const inputDecoration = InputDecoration( @@ -170,12 +253,28 @@ class _ManualTab extends StatelessWidget { child: Column( crossAxisAlignment: CrossAxisAlignment.stretch, children: [ + const Text( + 'Start by pairing with your local bridge. No account sign-in is ' + 'required.', + style: TextStyle( + color: Colors.white, + fontSize: 16, + fontWeight: FontWeight.w600, + ), + ), + const SizedBox(height: 8), + const Text( + 'Use the bridge\'s private Tailscale/WireGuard address. Public ' + 'internet bridge endpoints are outside the docs contract.', + style: TextStyle(color: Color(0xFF9CDCFE)), + ), + const SizedBox(height: 16), TextField( controller: urlController, style: const TextStyle(color: Colors.white), decoration: inputDecoration.copyWith( labelText: 'Bridge URL (wss://...)', - hintText: 'wss://192.168.1.100:8080', + hintText: 'wss://your-bridge.tailnet.ts.net:3000', hintStyle: const TextStyle(color: Colors.grey), ), ), @@ -184,8 +283,11 @@ class _ManualTab extends StatelessWidget { controller: tokenController, obscureText: true, style: const TextStyle(color: Colors.white), - decoration: - inputDecoration.copyWith(labelText: 'Auth Token (optional)'), + decoration: inputDecoration.copyWith( + labelText: 'Bridge Pairing Token', + helperText: 'Stored securely on-device after a successful pair.', + helperStyle: const TextStyle(color: Colors.grey), + ), ), const SizedBox(height: 24), if (error != null) diff --git a/apps/mobile/lib/features/startup/presentation/screens/splash_screen.dart b/apps/mobile/lib/features/startup/presentation/screens/splash_screen.dart new file mode 100644 index 0000000..c7ebdc8 --- /dev/null +++ b/apps/mobile/lib/features/startup/presentation/screens/splash_screen.dart @@ -0,0 +1,95 @@ +import 'dart:async'; + +import 'package:flutter/material.dart'; +import 'package:flutter_riverpod/flutter_riverpod.dart'; +import 'package:flutter_svg/flutter_svg.dart'; +import 'package:go_router/go_router.dart'; + +import '../../domain/bridge_startup_controller.dart'; + +class SplashScreen extends ConsumerStatefulWidget { + const SplashScreen({super.key}); + + @override + ConsumerState createState() => _SplashScreenState(); +} + +class _SplashScreenState extends ConsumerState + with SingleTickerProviderStateMixin { + late final AnimationController _controller; + late final Animation _opacity; + + @override + void initState() { + super.initState(); + _controller = AnimationController( + vsync: this, + duration: const Duration(milliseconds: 900), + ); + _opacity = CurvedAnimation(parent: _controller, curve: Curves.easeIn); + _controller.forward(); + unawaited(_restoreStartup()); + } + + Future _restoreStartup() async { + await Future.delayed(const Duration(milliseconds: 1200)); + final result = await ref.read(bridgeStartupControllerProvider).restore(); + ref.read(bridgeStartupErrorProvider.notifier).state = result.message; + + if (!mounted) { + return; + } + + switch (result.destination) { + case AppStartupDestination.bridgeSetup: + context.go('/bridge-setup'); + return; + case AppStartupDestination.home: + context.go('/home/chat'); + return; + } + } + + @override + void dispose() { + _controller.dispose(); + super.dispose(); + } + + @override + Widget build(BuildContext context) { + return Scaffold( + key: const Key('splashScreen'), + backgroundColor: const Color(0xFF1E1E1E), + body: Center( + child: FadeTransition( + opacity: _opacity, + child: Column( + mainAxisSize: MainAxisSize.min, + children: [ + SvgPicture.asset( + 'assets/branding/recursor_logo_dark.svg', + width: 200, + fit: BoxFit.contain, + ), + const SizedBox(height: 24), + const Text( + 'Restore Bridge Session', + style: TextStyle( + color: Colors.white, + fontSize: 22, + fontWeight: FontWeight.w600, + ), + ), + const SizedBox(height: 8), + const Text( + 'Checking for a saved bridge pairing…', + style: TextStyle(color: Color(0xFF9CDCFE)), + ), + ], + ), + ), + ), + ); + } +} diff --git a/docs/wireframes/01-auth.md b/docs/wireframes/01-auth.md deleted file mode 100644 index 2d370cc..0000000 --- a/docs/wireframes/01-auth.md +++ /dev/null @@ -1,125 +0,0 @@ -# 01 - Authentication Screens - -> Phase 1 — Login, OAuth, and onboarding. - ---- - -## 1A. Splash Screen - -``` -+---------------------------------------+ -| | -| | -| | -| | -| [ App Logo ] | -| | -| ReCursor | -| AI Coding Agents, Anywhere | -| | -| | -| ( loading spinner ) | -| | -| | -| | -+---------------------------------------+ -``` - -**Behavior:** -- Auto-checks for stored auth token -- If valid token found -> navigate to Bridge Pairing or Main Shell -- If no token -> navigate to Login Screen -- Duration: 1-2s max - ---- - -## 1B. Login Screen - -``` -+---------------------------------------+ -| ReCursor | -+---------------------------------------+ -| | -| [ App Logo ] | -| | -| Control your AI coding agents | -| from anywhere. | -| | -| | -| +----------------------------------+ | -| | | | -| | [G] Sign in with GitHub | | -| | | | -| +----------------------------------+ | -| | -| | -| ---- or ---- | -| | -| | -| +----------------------------------+ | -| | Personal Access Token | | -| | +----------------------------+ | | -| | | ghp_xxxxxxxxxxxxxxxxxxxx | | | -| | +----------------------------+ | | -| | | | -| | [ Connect with PAT ] | | -| +----------------------------------+ | -| | -| | -| By continuing, you agree to the | -| Terms of Service & Privacy Policy | -| | -+---------------------------------------+ -``` - -**Elements:** -- GitHub OAuth button (primary, filled, with GitHub icon) -- PAT input section (expandable/collapsible, secondary option) -- PAT field: obscured text input with show/hide toggle -- Legal links at bottom - -**States:** -- Default: OAuth button prominent, PAT collapsed -- PAT expanded: text field visible with connect button -- Loading: button shows spinner, inputs disabled -- Error: red banner below input with message ("Invalid token", "Auth failed") - ---- - -## 1C. OAuth WebView - -``` -+---------------------------------------+ -| [X] GitHub Login | -+---------------------------------------+ -| | -| +----------------------------------+ | -| | | | -| | github.com/login/oauth | | -| | | | -| | Username or email address | | -| | +----------------------------+ | | -| | | | | | -| | +----------------------------+ | | -| | | | -| | Password | | -| | +----------------------------+ | | -| | | | | | -| | +----------------------------+ | | -| | | | -| | [ Sign in ] | | -| | | | -| +----------------------------------+ | -| | -| ( progress bar at top of webview ) | -| | -+---------------------------------------+ -``` - -**Behavior:** -- Opens GitHub OAuth authorize URL in in-app WebView -- Intercepts redirect to `remotecli://authed?code=xxx` -- Exchanges code for token in background -- On success: close WebView, navigate to Bridge Pairing -- On failure: show error toast, return to Login Screen -- [X] button cancels and returns to Login diff --git a/docs/wireframes/01-startup.md b/docs/wireframes/01-startup.md new file mode 100644 index 0000000..1734b67 --- /dev/null +++ b/docs/wireframes/01-startup.md @@ -0,0 +1,73 @@ +# 01 - Startup & Bridge Restore + +> Phase 1 — bridge-first launch, saved pairing restore, and handoff to bridge setup. + +--- + +## 1A. Splash / Restore Screen + +``` ++---------------------------------------+ +| | +| | +| | +| | +| [ App Logo ] | +| | +| ReCursor | +| Restore Bridge Session | +| | +| Checking for a saved bridge pair... | +| | +| ( loading spinner ) | +| | +| | +| | ++---------------------------------------+ +``` + +**Behavior:** +- Auto-checks for a saved bridge URL and bridge pairing token +- If a valid saved pairing reconnects successfully -> navigate to Main Shell +- If no pairing exists or reconnect fails -> navigate to Bridge Setup +- Duration: 1-2s max while restore runs + +--- + +## 1B. Restore Failure Handoff + +``` ++---------------------------------------+ +| Bridge Setup | ++---------------------------------------+ +| | +| Unable to reconnect to the saved | +| bridge. Check the URL or pairing | +| token below and try again. | +| | +| Bridge URL | +| +-------------------------------+ | +| | wss://devbox.tailnet.ts.net | | +| +-------------------------------+ | +| | +| Bridge Pairing Token | +| +-------------------------------+ | +| | •••••••••••••••••••••••••••• | | +| +-------------------------------+ | +| | +| [ Reconnect to Bridge ] | +| | ++---------------------------------------+ +``` + +**Elements:** +- Error banner explaining why startup fell back to setup +- Saved bridge URL prefilled for quick correction +- Secure pairing token field with masked value +- Primary reconnect button + +**States:** +- Restore failed: error copy visible and fields prefilled +- Missing pairing: no error, blank fields +- Loading: reconnect button shows spinner, inputs disabled +- Success: navigate directly to Sessions list From 64d27887c24ab3dcce5679203c729f3829d9ea67 Mon Sep 17 00:00:00 2001 From: MasuRii Date: Fri, 20 Mar 2026 12:55:15 +0800 Subject: [PATCH 14/22] refactor(mobile): simplify router and home shell after auth removal Remove auth guards and simplify navigation flow. Update router to use new startup screens and remove auth-based redirection logic. - Simplify router.dart to remove auth state dependencies - Update home_shell.dart to use connection status bar - Refactor settings_screen.dart for cleaner navigation --- apps/mobile/lib/core/config/router.dart | 234 ++---------------- apps/mobile/lib/features/home/home_shell.dart | 122 ++------- .../presentation/screens/settings_screen.dart | 170 +++++++------ 3 files changed, 141 insertions(+), 385 deletions(-) diff --git a/apps/mobile/lib/core/config/router.dart b/apps/mobile/lib/core/config/router.dart index 7068021..e5c7704 100644 --- a/apps/mobile/lib/core/config/router.dart +++ b/apps/mobile/lib/core/config/router.dart @@ -1,220 +1,30 @@ -import 'package:flutter/material.dart'; import 'package:flutter_riverpod/flutter_riverpod.dart'; import 'package:go_router/go_router.dart'; -import '../auth/auth_provider.dart'; -import '../auth/auth_state.dart'; -import '../network/connection_state.dart' as cs; -import '../providers/websocket_provider.dart'; -import '../../features/auth/presentation/screens/splash_screen.dart'; -import '../../features/auth/presentation/screens/login_screen.dart'; -import '../../features/auth/presentation/screens/bridge_setup_screen.dart'; -import '../../features/chat/presentation/screens/session_list_screen.dart'; +import '../../features/agents/presentation/screens/agent_list_screen.dart'; +import '../../features/approvals/presentation/screens/approval_detail_screen.dart'; +import '../../features/approvals/presentation/screens/approvals_screen.dart'; import '../../features/chat/presentation/screens/chat_screen.dart'; +import '../../features/chat/presentation/screens/session_list_screen.dart'; import '../../features/diff/presentation/screens/diff_viewer_screen.dart'; +import '../../features/git/presentation/screens/git_screen.dart'; +import '../../features/home/home_shell.dart'; import '../../features/repos/presentation/screens/file_tree_screen.dart'; import '../../features/repos/presentation/screens/file_viewer_screen.dart'; +import '../../features/settings/presentation/screens/settings_screen.dart'; +import '../../features/startup/presentation/screens/bridge_setup_screen.dart'; +import '../../features/startup/presentation/screens/splash_screen.dart'; +import '../../features/terminal/presentation/screens/terminal_screen.dart'; -// --------------------------------------------------------------------------- -// Placeholder screens -// --------------------------------------------------------------------------- - -class _GitScreen extends StatelessWidget { - const _GitScreen(); - - @override - Widget build(BuildContext context) { - return Scaffold( - appBar: AppBar(title: const Text('Git')), - body: const Center(child: Text('Git')), - ); - } -} - -class _ApprovalsScreen extends StatelessWidget { - const _ApprovalsScreen(); - - @override - Widget build(BuildContext context) { - return Scaffold( - appBar: AppBar(title: const Text('Approvals')), - body: const Center(child: Text('Approvals')), - ); - } -} - -class _SettingsScreen extends StatelessWidget { - const _SettingsScreen(); - - @override - Widget build(BuildContext context) { - return Scaffold( - appBar: AppBar(title: const Text('Settings')), - body: const Center(child: Text('Settings')), - ); - } -} - -class _AgentListScreen extends StatelessWidget { - const _AgentListScreen(); - - @override - Widget build(BuildContext context) { - return Scaffold( - appBar: AppBar(title: const Text('Agents')), - body: const Center(child: Text('Agents')), - ); - } -} - -class _ApprovalDetailScreen extends StatelessWidget { - final String id; - const _ApprovalDetailScreen({required this.id}); - - @override - Widget build(BuildContext context) { - return Scaffold( - appBar: AppBar(title: const Text('Approval Detail')), - body: Center(child: Text('Approval: $id')), - ); - } -} - -class _TerminalScreen extends StatelessWidget { - const _TerminalScreen(); - - @override - Widget build(BuildContext context) { - return Scaffold( - appBar: AppBar(title: const Text('Terminal')), - body: const Center(child: Text('Terminal')), - ); - } -} - -// --------------------------------------------------------------------------- -// Home shell -// --------------------------------------------------------------------------- - -class HomeShell extends ConsumerStatefulWidget { - final StatefulNavigationShell navigationShell; - const HomeShell({super.key, required this.navigationShell}); - - @override - ConsumerState createState() => _HomeShellState(); -} - -class _HomeShellState extends ConsumerState { - static const _items = [ - BottomNavigationBarItem(icon: Icon(Icons.chat), label: 'Chat'), - BottomNavigationBarItem(icon: Icon(Icons.difference), label: 'Diff'), - BottomNavigationBarItem(icon: Icon(Icons.folder_outlined), label: 'Files'), - BottomNavigationBarItem(icon: Icon(Icons.source), label: 'Git'), - BottomNavigationBarItem(icon: Icon(Icons.approval), label: 'Approvals'), - BottomNavigationBarItem(icon: Icon(Icons.settings), label: 'Settings'), - ]; - - @override - Widget build(BuildContext context) { - return Scaffold( - body: Column( - children: [ - const ConnectionStatusBar(), - Expanded(child: widget.navigationShell), - ], - ), - bottomNavigationBar: BottomNavigationBar( - currentIndex: widget.navigationShell.currentIndex, - items: _items, - onTap: (index) => widget.navigationShell.goBranch( - index, - initialLocation: index == widget.navigationShell.currentIndex, - ), - ), - ); - } -} - -// --------------------------------------------------------------------------- -// ConnectionStatusBar (inline — also exported from shared/widgets) -// --------------------------------------------------------------------------- - -class ConnectionStatusBar extends ConsumerWidget { - const ConnectionStatusBar({super.key}); - - @override - Widget build(BuildContext context, WidgetRef ref) { - final statusAsync = ref.watch(connectionStatusProvider); - return statusAsync.when( - data: (status) => _bar(status), - loading: () => const SizedBox.shrink(), - error: (_, __) => const SizedBox.shrink(), - ); - } - - Widget _bar(cs.ConnectionStatus status) { - if (status == cs.ConnectionStatus.connected) return const SizedBox.shrink(); - - final isReconnecting = status == cs.ConnectionStatus.reconnecting; - final color = isReconnecting ? const Color(0xFFFF9800) : const Color(0xFFF44747); - final message = isReconnecting ? 'Reconnecting...' : 'Offline'; - - return Container( - width: double.infinity, - color: color, - padding: const EdgeInsets.symmetric(vertical: 3), - child: Text( - message, - textAlign: TextAlign.center, - style: const TextStyle( - color: Colors.white, - fontSize: 12, - fontWeight: FontWeight.w500, - ), - ), - ); - } -} - -// --------------------------------------------------------------------------- -// Router -// --------------------------------------------------------------------------- - -GoRouter _buildRouter(AuthState authState) { +GoRouter _buildRouter() { return GoRouter( initialLocation: '/splash', - redirect: (context, state) { - final status = authState.status; - final location = state.matchedLocation; - - if (status == AuthStatus.loading) return null; - - if (status == AuthStatus.unauthenticated) { - if (location == '/login' || location == '/splash') return null; - return '/login'; - } - - if (status == AuthStatus.authenticated) { - if (location == '/login' || location == '/splash') { - return '/home/chat'; - } - } - - return null; - }, routes: [ - GoRoute( - path: '/', - redirect: (_, __) => '/splash', - ), + GoRoute(path: '/', redirect: (_, __) => '/splash'), GoRoute( path: '/splash', builder: (_, __) => const SplashScreen(), ), - GoRoute( - path: '/login', - builder: (_, __) => const LoginScreen(), - ), GoRoute( path: '/bridge-setup', builder: (_, __) => const BridgeSetupScreen(), @@ -263,7 +73,7 @@ GoRouter _buildRouter(AuthState authState) { routes: [ GoRoute( path: '/home/git', - builder: (_, __) => const _GitScreen(), + builder: (_, __) => const GitScreen(sessionId: ''), ), ], ), @@ -271,7 +81,7 @@ GoRouter _buildRouter(AuthState authState) { routes: [ GoRoute( path: '/home/approvals', - builder: (_, __) => const _ApprovalsScreen(), + builder: (_, __) => const ApprovalsScreen(), ), ], ), @@ -279,7 +89,7 @@ GoRouter _buildRouter(AuthState authState) { routes: [ GoRoute( path: '/home/settings', - builder: (_, __) => const _SettingsScreen(), + builder: (_, __) => const SettingsScreen(), ), ], ), @@ -287,16 +97,17 @@ GoRouter _buildRouter(AuthState authState) { ), GoRoute( path: '/home/agents', - builder: (_, __) => const _AgentListScreen(), + builder: (_, __) => const AgentListScreen(), ), GoRoute( path: '/approval/:id', builder: (_, state) => - _ApprovalDetailScreen(id: state.pathParameters['id']!), + ApprovalDetailScreen(toolCallId: state.pathParameters['id']!), ), GoRoute( path: '/terminal', - builder: (_, __) => const _TerminalScreen(), + builder: (_, __) => + const TerminalScreen(sessionId: 'default', workingDirectory: '~'), ), GoRoute( path: '/home/repos/view', @@ -312,13 +123,8 @@ GoRouter _buildRouter(AuthState authState) { ); } -// --------------------------------------------------------------------------- -// Providers -// --------------------------------------------------------------------------- - final routerProvider = Provider((ref) { - final authState = ref.watch(authStateProvider); - return _buildRouter(authState); + return _buildRouter(); }); final appRouter = Provider((ref) => ref.watch(routerProvider)); diff --git a/apps/mobile/lib/features/home/home_shell.dart b/apps/mobile/lib/features/home/home_shell.dart index 4c58b53..0cd6c5f 100644 --- a/apps/mobile/lib/features/home/home_shell.dart +++ b/apps/mobile/lib/features/home/home_shell.dart @@ -1,71 +1,43 @@ import 'package:flutter/material.dart'; -import 'package:flutter_riverpod/flutter_riverpod.dart'; import 'package:go_router/go_router.dart'; -import '../../core/network/connection_state.dart' as cs; -import '../../core/providers/websocket_provider.dart'; -import '../approvals/domain/providers/approval_provider.dart'; +import '../../shared/widgets/connection_status_bar.dart'; /// Root shell widget that wraps the bottom-navigation branches. /// -/// Renders a [ConnectionStatusBar] overlaid at the top of the body, and a -/// [BottomNavigationBar] with badge support for pending approvals. -class HomeShell extends ConsumerWidget { +/// This stays feature-owned while preserving the existing router behavior. +class HomeShell extends StatelessWidget { + const HomeShell({super.key, required this.navigationShell}); + final StatefulNavigationShell navigationShell; - const HomeShell({super.key, required this.navigationShell}); + static const List _items = [ + BottomNavigationBarItem(icon: Icon(Icons.chat), label: 'Chat'), + BottomNavigationBarItem(icon: Icon(Icons.difference), label: 'Diff'), + BottomNavigationBarItem( + icon: Icon(Icons.folder_outlined), + label: 'Files', + ), + BottomNavigationBarItem(icon: Icon(Icons.source), label: 'Git'), + BottomNavigationBarItem( + icon: Icon(Icons.approval), + label: 'Approvals', + ), + BottomNavigationBarItem(icon: Icon(Icons.settings), label: 'Settings'), + ]; @override - Widget build(BuildContext context, WidgetRef ref) { - final pendingCount = ref.watch(pendingApprovalsProvider).length; - + Widget build(BuildContext context) { return Scaffold( - body: Stack( + body: Column( children: [ - // Main content - navigationShell, - // Connection status overlay at top - const Positioned( - top: 0, - left: 0, - right: 0, - child: _ConnectionStatusBar(), - ), + const ConnectionStatusBar(), + Expanded(child: navigationShell), ], ), bottomNavigationBar: BottomNavigationBar( currentIndex: navigationShell.currentIndex, - type: BottomNavigationBarType.fixed, - items: [ - const BottomNavigationBarItem( - icon: Icon(Icons.chat_bubble_outline), - label: 'Chat', - ), - const BottomNavigationBarItem( - icon: Icon(Icons.difference_outlined), - label: 'Diff', - ), - const BottomNavigationBarItem( - icon: Icon(Icons.folder_outlined), - label: 'Files', - ), - const BottomNavigationBarItem( - icon: Icon(Icons.source_outlined), - label: 'Git', - ), - BottomNavigationBarItem( - icon: Badge( - isLabelVisible: pendingCount > 0, - label: Text('$pendingCount'), - child: const Icon(Icons.checklist_outlined), - ), - label: 'Approvals', - ), - const BottomNavigationBarItem( - icon: Icon(Icons.settings_outlined), - label: 'Settings', - ), - ], + items: _items, onTap: (index) => navigationShell.goBranch( index, initialLocation: index == navigationShell.currentIndex, @@ -74,49 +46,3 @@ class HomeShell extends ConsumerWidget { ); } } - -// --------------------------------------------------------------------------- -// Connection status bar -// --------------------------------------------------------------------------- - -class _ConnectionStatusBar extends ConsumerWidget { - const _ConnectionStatusBar(); - - @override - Widget build(BuildContext context, WidgetRef ref) { - final statusAsync = ref.watch(connectionStatusProvider); - return statusAsync.when( - data: (status) => _bar(status), - loading: () => const SizedBox.shrink(), - error: (_, __) => const SizedBox.shrink(), - ); - } - - Widget _bar(cs.ConnectionStatus status) { - if (status == cs.ConnectionStatus.connected) return const SizedBox.shrink(); - - final isReconnecting = status == cs.ConnectionStatus.reconnecting; - final color = isReconnecting - ? const Color(0xFFFF9800) - : const Color(0xFFF44747); - final message = isReconnecting ? 'Reconnecting…' : 'Offline'; - - return Material( - color: Colors.transparent, - child: Container( - width: double.infinity, - color: color, - padding: const EdgeInsets.symmetric(vertical: 3), - child: Text( - message, - textAlign: TextAlign.center, - style: const TextStyle( - color: Colors.white, - fontSize: 12, - fontWeight: FontWeight.w500, - ), - ), - ), - ); - } -} diff --git a/apps/mobile/lib/features/settings/presentation/screens/settings_screen.dart b/apps/mobile/lib/features/settings/presentation/screens/settings_screen.dart index db82722..f782965 100644 --- a/apps/mobile/lib/features/settings/presentation/screens/settings_screen.dart +++ b/apps/mobile/lib/features/settings/presentation/screens/settings_screen.dart @@ -1,30 +1,19 @@ +import 'dart:async'; + import 'package:flutter/material.dart'; import 'package:flutter_riverpod/flutter_riverpod.dart'; +import 'package:go_router/go_router.dart'; -import '../../../../core/auth/auth_provider.dart'; +import '../../../../core/network/connection_state.dart'; +import '../../../../core/providers/bridge_provider.dart'; import '../../../../core/providers/theme_provider.dart'; -import '../../../../core/providers/websocket_provider.dart'; -import '../../../../core/storage/preferences.dart'; +import '../../../../core/providers/token_storage_provider.dart'; +import '../../../../core/storage/secure_token_storage.dart'; import '../widgets/setting_tile.dart'; -// --------------------------------------------------------------------------- -// Providers -// --------------------------------------------------------------------------- - -final _preferencesProvider = Provider((ref) { - throw UnimplementedError('Override in ProviderScope overrides'); -}); - final _themeModeProvider = StateProvider((ref) => ThemeMode.system); - final _notificationsEnabledProvider = StateProvider((ref) => true); -// --------------------------------------------------------------------------- -// Settings screen -// --------------------------------------------------------------------------- - -/// Main settings screen grouped into Appearance, Notifications, Bridge, -/// Account, and About sections. class SettingsScreen extends ConsumerWidget { const SettingsScreen({super.key}); @@ -33,13 +22,15 @@ class SettingsScreen extends ConsumerWidget { final themeMode = ref.watch(_themeModeProvider); final notificationsEnabled = ref.watch(_notificationsEnabledProvider); final highContrast = ref.watch(highContrastProvider); - final authState = ref.watch(authStateProvider); + final bridgeStatus = ref.watch(bridgeProvider); + final preferences = ref.watch(appPreferencesProvider); + final bridgeUrl = preferences.getBridgeUrl(); return Scaffold( appBar: AppBar(title: const Text('Settings')), body: ListView( children: [ - _SectionHeader(label: 'APPEARANCE'), + const _SectionHeader(label: 'APPEARANCE'), Padding( padding: const EdgeInsets.symmetric(horizontal: 16, vertical: 8), child: SegmentedButton( @@ -50,8 +41,7 @@ class SettingsScreen extends ConsumerWidget { ], selected: {themeMode}, onSelectionChanged: (selection) { - ref.read(_themeModeProvider.notifier).state = - selection.first; + ref.read(_themeModeProvider.notifier).state = selection.first; }, ), ), @@ -60,83 +50,104 @@ class SettingsScreen extends ConsumerWidget { title: const Text('High contrast'), subtitle: const Text('Increases contrast for better visibility'), value: highContrast, - onChanged: (v) { - ref.read(highContrastProvider.notifier).setHighContrast(v); + onChanged: (value) { + ref.read(highContrastProvider.notifier).setHighContrast(value); }, ), const Divider(height: 1), - - _SectionHeader(label: 'NOTIFICATIONS'), + const _SectionHeader(label: 'NOTIFICATIONS'), SwitchListTile( contentPadding: const EdgeInsets.symmetric(horizontal: 16), title: const Text('Enable notifications'), value: notificationsEnabled, - onChanged: (v) { - ref.read(_notificationsEnabledProvider.notifier).state = v; + onChanged: (value) { + ref.read(_notificationsEnabledProvider.notifier).state = value; }, ), const Divider(height: 1), - - _SectionHeader(label: 'BRIDGE'), + const _SectionHeader(label: 'BRIDGE'), SettingTile( leading: const Icon(Icons.link, size: 20), - title: const Text('Bridge URL'), - subtitle: const Text( - 'Not connected', - style: TextStyle(color: Color(0xFF9E9E9E), fontSize: 12), + title: const Text('Saved bridge'), + subtitle: Text( + bridgeUrl == null || bridgeUrl.isEmpty + ? 'No bridge paired yet' + : bridgeUrl, + style: const TextStyle( + color: Color(0xFF9E9E9E), + fontSize: 12, + ), ), ), SettingTile( - leading: const Icon(Icons.link_off, size: 20, - color: Color(0xFFF44747)), - title: const Text( - 'Disconnect', - style: TextStyle(color: Color(0xFFF44747)), + leading: const Icon(Icons.route, size: 20), + title: const Text('Run bridge setup'), + subtitle: const Text( + 'Update the saved bridge URL or pairing token', + style: TextStyle(fontSize: 12, color: Color(0xFF9E9E9E)), ), - showDivider: false, - onTap: () { - final service = ref.read(webSocketServiceProvider); - service.disconnect(); - ScaffoldMessenger.of(context).showSnackBar( - const SnackBar(content: Text('Disconnected from bridge')), - ); - }, + onTap: () => context.go('/bridge-setup'), ), - const Divider(height: 1), - - _SectionHeader(label: 'ACCOUNT'), SettingTile( - leading: authState.avatarUrl != null - ? CircleAvatar( - backgroundImage: - NetworkImage(authState.avatarUrl!), - radius: 16, - ) - : const CircleAvatar( - radius: 16, - child: Icon(Icons.person, size: 18), - ), - title: Text(authState.username ?? 'Unknown user'), - subtitle: const Text( - 'GitHub', - style: TextStyle(fontSize: 11, color: Color(0xFF9E9E9E)), + leading: Icon( + bridgeStatus == ConnectionStatus.connected + ? Icons.link_off + : Icons.link, + size: 20, + color: bridgeStatus == ConnectionStatus.connected + ? const Color(0xFFF44747) + : const Color(0xFF9E9E9E), + ), + title: Text( + bridgeStatus == ConnectionStatus.connected + ? 'Disconnect' + : 'Bridge offline', + style: TextStyle( + color: bridgeStatus == ConnectionStatus.connected + ? const Color(0xFFF44747) + : const Color(0xFF9E9E9E), + ), + ), + subtitle: Text( + switch (bridgeStatus) { + ConnectionStatus.connected => 'Connected to the paired bridge', + ConnectionStatus.connecting => 'Connecting…', + ConnectionStatus.reconnecting => 'Reconnecting…', + ConnectionStatus.error => 'Last bridge connection failed', + ConnectionStatus.disconnected => 'No active bridge connection', + }, + style: const TextStyle(fontSize: 12, color: Color(0xFF9E9E9E)), ), + onTap: bridgeStatus == ConnectionStatus.connected + ? () { + ref.read(bridgeProvider.notifier).disconnect(); + ScaffoldMessenger.of(context).showSnackBar( + const SnackBar(content: Text('Disconnected from bridge')), + ); + } + : null, ), SettingTile( - leading: const Icon(Icons.logout, size: 20, - color: Color(0xFFF44747)), + leading: const Icon( + Icons.delete_outline, + size: 20, + color: Color(0xFFF44747), + ), title: const Text( - 'Sign Out', + 'Forget saved pairing', style: TextStyle(color: Color(0xFFF44747)), ), + subtitle: const Text( + 'Clears the saved bridge URL and pairing token', + style: TextStyle(fontSize: 12, color: Color(0xFF9E9E9E)), + ), showDivider: false, onTap: () { - ref.read(authStateProvider.notifier).signOut(); + unawaited(_forgetSavedPairing(context, ref)); }, ), const Divider(height: 1), - - _SectionHeader(label: 'ABOUT'), + const _SectionHeader(label: 'ABOUT'), const SettingTile( leading: Icon(Icons.info_outline, size: 20), title: Text('Version'), @@ -163,7 +174,6 @@ class SettingsScreen extends ConsumerWidget { title: const Text('GitHub'), showDivider: false, onTap: () { - // Link would be opened via url_launcher in a real implementation. ScaffoldMessenger.of(context).showSnackBar( const SnackBar( content: Text('https://github.com/RecursiveDev/ReCursor'), @@ -176,13 +186,27 @@ class SettingsScreen extends ConsumerWidget { ), ); } + + Future _forgetSavedPairing(BuildContext context, WidgetRef ref) async { + ref.read(bridgeProvider.notifier).disconnect(); + await ref.read(appPreferencesProvider).setBridgeUrl(null); + await ref.read(tokenStorageProvider).deleteToken(kBridgeToken); + + if (!context.mounted) { + return; + } + + ScaffoldMessenger.of(context).showSnackBar( + const SnackBar(content: Text('Cleared saved bridge pairing')), + ); + } } class _SectionHeader extends StatelessWidget { - final String label; - const _SectionHeader({required this.label}); + final String label; + @override Widget build(BuildContext context) { return Padding( From 37e2444e418187bf9959acf627b559bbcd2d5b0f Mon Sep 17 00:00:00 2001 From: MasuRii Date: Fri, 20 Mar 2026 12:55:30 +0800 Subject: [PATCH 15/22] feat(mobile): enhance core network, storage and sync infrastructure Add bridge connection validator and secure token storage implementations. Extend websocket service with reconnection logic and message handling. Enhance sync queue with comprehensive message queuing and retry logic. Add provider files for DI integration. - Add bridge_connection_validator.dart for connection testing - Add secure_token_storage.dart with flutter_secure_storage - Extend sync_queue.dart with queue management - Add sync_queue_provider.dart and token_storage_provider.dart - Enhance websocket_service.dart with connection management - Update database.dart schema for message persistence --- .../network/bridge_connection_validator.dart | 62 +++++ .../lib/core/network/websocket_service.dart | 254 +++++++++++++----- .../core/providers/sync_queue_provider.dart | 9 + .../providers/token_storage_provider.dart | 12 + apps/mobile/lib/core/storage/database.dart | 7 + .../core/storage/secure_token_storage.dart | 28 ++ apps/mobile/lib/core/sync/sync_queue.dart | 139 +++++++++- 7 files changed, 428 insertions(+), 83 deletions(-) create mode 100644 apps/mobile/lib/core/network/bridge_connection_validator.dart create mode 100644 apps/mobile/lib/core/providers/sync_queue_provider.dart create mode 100644 apps/mobile/lib/core/providers/token_storage_provider.dart create mode 100644 apps/mobile/lib/core/storage/secure_token_storage.dart diff --git a/apps/mobile/lib/core/network/bridge_connection_validator.dart b/apps/mobile/lib/core/network/bridge_connection_validator.dart new file mode 100644 index 0000000..af27e50 --- /dev/null +++ b/apps/mobile/lib/core/network/bridge_connection_validator.dart @@ -0,0 +1,62 @@ +class BridgeConnectionValidationResult { + const BridgeConnectionValidationResult._({ + required this.isValid, + this.errorMessage, + }); + + const BridgeConnectionValidationResult.valid() : this._(isValid: true); + + const BridgeConnectionValidationResult.invalid(String message) + : this._(isValid: false, errorMessage: message); + + final bool isValid; + final String? errorMessage; +} + +class BridgeConnectionValidator { + const BridgeConnectionValidator._(); + + static BridgeConnectionValidationResult validate({ + required String url, + required String token, + }) { + final normalizedUrl = url.trim(); + final normalizedToken = token.trim(); + + if (normalizedUrl.isEmpty) { + return const BridgeConnectionValidationResult.invalid( + 'Bridge URL is required.', + ); + } + + if (normalizedToken.isEmpty) { + return const BridgeConnectionValidationResult.invalid( + 'Bridge auth token is required.', + ); + } + + final uri = Uri.tryParse(normalizedUrl); + if (uri == null || !uri.hasScheme || uri.host.isEmpty) { + return const BridgeConnectionValidationResult.invalid( + 'Enter a valid bridge URL.', + ); + } + + if (uri.scheme != 'wss') { + return const BridgeConnectionValidationResult.invalid( + 'Bridge URL must use wss:// to match the security contract.', + ); + } + + return const BridgeConnectionValidationResult.valid(); + } +} + +class BridgeConnectionException implements Exception { + const BridgeConnectionException(this.message); + + final String message; + + @override + String toString() => message; +} diff --git a/apps/mobile/lib/core/network/websocket_service.dart b/apps/mobile/lib/core/network/websocket_service.dart index 2939863..2d99309 100644 --- a/apps/mobile/lib/core/network/websocket_service.dart +++ b/apps/mobile/lib/core/network/websocket_service.dart @@ -3,9 +3,12 @@ import 'dart:convert'; import 'package:web_socket_channel/web_socket_channel.dart'; +import 'bridge_connection_validator.dart'; import 'connection_state.dart'; import 'websocket_messages.dart'; +typedef WebSocketChannelFactory = WebSocketChannel Function(Uri uri); + /// WebSocket client service for communication with the ReCursor bridge server. /// /// Responsibilities: @@ -16,186 +19,295 @@ import 'websocket_messages.dart'; /// - Serialize outgoing [BridgeMessage] to JSON /// - Parse incoming JSON into [BridgeMessage] class WebSocketService { + WebSocketService({WebSocketChannelFactory? channelFactory}) + : _channelFactory = channelFactory ?? WebSocketChannel.connect; + static const int _heartbeatIntervalSeconds = 15; static const int _heartbeatTimeoutSeconds = 10; + static const int _authTimeoutSeconds = 10; static const int _maxReconnectDelaySeconds = 30; + final WebSocketChannelFactory _channelFactory; + WebSocketChannel? _channel; String? _url; String? _token; + Map? _lastConnectionAckPayload; - final _messageController = StreamController.broadcast(); - final _statusController = StreamController.broadcast(); + final StreamController _messageController = + StreamController.broadcast(); + final StreamController _statusController = + StreamController.broadcast(); ConnectionStatus _status = ConnectionStatus.disconnected; int _reconnectAttempts = 0; bool _intentionalDisconnect = false; + bool _authFailed = false; + Completer? _authCompleter; Timer? _heartbeatTimer; Timer? _pongTimeoutTimer; Timer? _reconnectTimer; - // --------------------------------------------------------------------------- - // Public streams - // --------------------------------------------------------------------------- - Stream get messages => _messageController.stream; Stream get connectionStatus => _statusController.stream; ConnectionStatus get currentStatus => _status; - - // --------------------------------------------------------------------------- - // Connect / Disconnect - // --------------------------------------------------------------------------- + Map? get lastConnectionAckPayload => + _lastConnectionAckPayload; Future connect({required String url, required String token}) async { - _url = url; - _token = token; + final validation = BridgeConnectionValidator.validate( + url: url, + token: token, + ); + if (!validation.isValid) { + throw BridgeConnectionException(validation.errorMessage!); + } + + _url = url.trim(); + _token = token.trim(); _intentionalDisconnect = false; + _authFailed = false; _reconnectAttempts = 0; await _doConnect(); } Future _doConnect() async { - _setStatus(ConnectionStatus.connecting); - - try { - final uri = Uri.parse(_url!); - _channel = WebSocketChannel.connect(uri); + if (_url == null || _token == null) { + throw const BridgeConnectionException( + 'Bridge connection details are incomplete.', + ); + } - // Wait for the channel to be ready (throws on auth/network failure). - await _channel!.ready; + if (_status != ConnectionStatus.reconnecting) { + _setStatus(ConnectionStatus.connecting); + } - _setStatus(ConnectionStatus.connected); - _reconnectAttempts = 0; + _cleanUp(closeChannel: true, cancelReconnect: false); + _authCompleter = Completer(); - // Send auth immediately. - send(BridgeMessage.auth( - token: _token!, - clientVersion: '0.1.0', - platform: _platformString(), - )); + try { + final Uri uri = Uri.parse(_url!); + final WebSocketChannel channel = _channelFactory(uri); + _channel = channel; - // Start listening to incoming frames. - _channel!.stream.listen( + channel.stream.listen( _onRawMessage, onError: _onError, onDone: _onDone, cancelOnError: false, ); + await channel.ready; + + _sendInternal( + BridgeMessage.auth( + token: _token!, + clientVersion: '0.1.0', + platform: _platformString(), + ), + ); + + await _authCompleter!.future.timeout( + const Duration(seconds: _authTimeoutSeconds), + onTimeout: () { + throw const BridgeConnectionException( + 'Bridge authentication timed out.', + ); + }, + ); + _startHeartbeat(); - } catch (e) { + } catch (error) { + _completeAuthError(error); _setStatus(ConnectionStatus.error); - _scheduleReconnect(); + _cleanUp(closeChannel: true, cancelReconnect: false); + _scheduleReconnectIfNeeded(); + if (error is BridgeConnectionException) { + rethrow; + } + throw BridgeConnectionException('Failed to connect to bridge: $error'); } } void disconnect() { _intentionalDisconnect = true; + _authFailed = false; + _completeAuthError( + const BridgeConnectionException('Bridge connection closed.'), + ); _cleanUp(); _setStatus(ConnectionStatus.disconnected); } - // --------------------------------------------------------------------------- - // Send - // --------------------------------------------------------------------------- - - void send(BridgeMessage message) { - if (_channel == null || _status != ConnectionStatus.connected) return; - _channel!.sink.add(message.toJsonString()); + bool send(BridgeMessage message) { + if (_channel == null || _status != ConnectionStatus.connected) { + return false; + } + return _sendInternal(message); } - /// Send raw JSON string — primarily for testing. void sendRaw(String json) { _channel?.sink.add(json); } - // --------------------------------------------------------------------------- - // Internal helpers - // --------------------------------------------------------------------------- + bool _sendInternal(BridgeMessage message) { + final WebSocketChannel? channel = _channel; + if (channel == null) { + return false; + } + + channel.sink.add(message.toJsonString()); + return true; + } void _onRawMessage(dynamic data) { try { - final json = jsonDecode(data as String) as Map; - final msg = BridgeMessage.fromJson(json); + final Map json = + jsonDecode(data as String) as Map; + final BridgeMessage message = BridgeMessage.fromJson(json); + + if (message.type == BridgeMessageType.connectionAck) { + _reconnectAttempts = 0; + _authFailed = false; + _lastConnectionAckPayload = Map.unmodifiable( + Map.from(message.payload), + ); + _setStatus(ConnectionStatus.connected); + _completeAuthSuccess(); + return; + } + + if (message.type == BridgeMessageType.connectionError) { + _authFailed = true; + final String detail = message.payload['message'] as String? ?? + 'Bridge rejected the auth token.'; + _completeAuthError(BridgeConnectionException(detail)); + _setStatus(ConnectionStatus.error); + _cleanUp(closeChannel: true, cancelReconnect: false); + return; + } - // Heartbeat pong — cancel timeout timer. - if (msg.type == BridgeMessageType.heartbeatPong) { + if (message.type == BridgeMessageType.heartbeatPong) { _pongTimeoutTimer?.cancel(); _pongTimeoutTimer = null; return; } - _messageController.add(msg); + if (!_messageController.isClosed) { + _messageController.add(message); + } } catch (_) { - // Malformed message — ignore. + // Ignore malformed frames from the bridge. } } void _onError(Object error) { + _completeAuthError( + BridgeConnectionException('Bridge socket error: $error')); _setStatus(ConnectionStatus.error); - _cleanUp(closeChannel: false); - if (!_intentionalDisconnect) _scheduleReconnect(); + _cleanUp(closeChannel: false, cancelReconnect: false); + _scheduleReconnectIfNeeded(); } void _onDone() { + _completeAuthError( + const BridgeConnectionException('Bridge connection closed.'), + ); _setStatus(ConnectionStatus.disconnected); - _cleanUp(closeChannel: false); - if (!_intentionalDisconnect) _scheduleReconnect(); + _cleanUp(closeChannel: false, cancelReconnect: false); + _scheduleReconnectIfNeeded(); } void _startHeartbeat() { _heartbeatTimer?.cancel(); _heartbeatTimer = Timer.periodic( - Duration(seconds: _heartbeatIntervalSeconds), + const Duration(seconds: _heartbeatIntervalSeconds), (_) => _sendPing(), ); } void _sendPing() { - if (_status != ConnectionStatus.connected) return; - send(BridgeMessage.heartbeatPing()); + if (_status != ConnectionStatus.connected) { + return; + } + + final bool sent = send(BridgeMessage.heartbeatPing()); + if (!sent) { + return; + } - // Expect pong within timeout window. _pongTimeoutTimer?.cancel(); _pongTimeoutTimer = Timer( - Duration(seconds: _heartbeatTimeoutSeconds), + const Duration(seconds: _heartbeatTimeoutSeconds), _onPongTimeout, ); } void _onPongTimeout() { - // No pong received — trigger reconnect. - _cleanUp(closeChannel: true); + _cleanUp(closeChannel: true, cancelReconnect: false); _setStatus(ConnectionStatus.reconnecting); - if (!_intentionalDisconnect) _scheduleReconnect(); + _scheduleReconnectIfNeeded(); + } + + void _scheduleReconnectIfNeeded() { + if (_intentionalDisconnect || _authFailed) { + return; + } + _scheduleReconnect(); } void _scheduleReconnect() { - if (_intentionalDisconnect) return; _reconnectTimer?.cancel(); - final delaySeconds = _exponentialDelay(_reconnectAttempts); + final int delaySeconds = _exponentialDelay(_reconnectAttempts); _reconnectAttempts++; _setStatus(ConnectionStatus.reconnecting); _reconnectTimer = Timer(Duration(seconds: delaySeconds), () async { - if (!_intentionalDisconnect) await _doConnect(); + if (_intentionalDisconnect || _authFailed) { + return; + } + + try { + await _doConnect(); + } catch (_) { + // Reconnect failures are surfaced through connectionStatus. + } }); } int _exponentialDelay(int attempt) { - final delay = (1 << attempt).clamp(1, _maxReconnectDelaySeconds); + final int delay = (1 << attempt).clamp(1, _maxReconnectDelaySeconds); return delay; } - void _cleanUp({bool closeChannel = true}) { + void _completeAuthSuccess() { + final Completer? completer = _authCompleter; + if (completer != null && !completer.isCompleted) { + completer.complete(); + } + } + + void _completeAuthError(Object error) { + final Completer? completer = _authCompleter; + if (completer != null && !completer.isCompleted) { + completer.completeError(error); + } + } + + void _cleanUp({ + bool closeChannel = true, + bool cancelReconnect = true, + }) { _heartbeatTimer?.cancel(); _heartbeatTimer = null; _pongTimeoutTimer?.cancel(); _pongTimeoutTimer = null; - _reconnectTimer?.cancel(); - _reconnectTimer = null; + if (cancelReconnect) { + _reconnectTimer?.cancel(); + _reconnectTimer = null; + } if (closeChannel) { _channel?.sink.close(); @@ -205,16 +317,20 @@ class WebSocketService { void _setStatus(ConnectionStatus status) { _status = status; - _statusController.add(status); + if (!_statusController.isClosed) { + _statusController.add(status); + } } String _platformString() { - // In a full implementation, use Platform.isIOS / Platform.isAndroid. return 'flutter'; } void dispose() { _intentionalDisconnect = true; + _completeAuthError( + const BridgeConnectionException('Bridge connection disposed.'), + ); _cleanUp(); _messageController.close(); _statusController.close(); diff --git a/apps/mobile/lib/core/providers/sync_queue_provider.dart b/apps/mobile/lib/core/providers/sync_queue_provider.dart new file mode 100644 index 0000000..dff3d06 --- /dev/null +++ b/apps/mobile/lib/core/providers/sync_queue_provider.dart @@ -0,0 +1,9 @@ +import 'package:flutter_riverpod/flutter_riverpod.dart'; + +import '../sync/sync_queue.dart'; +import 'database_provider.dart'; + +final syncQueueServiceProvider = Provider((ref) { + final database = ref.watch(databaseProvider); + return SyncQueueService(database: database); +}); diff --git a/apps/mobile/lib/core/providers/token_storage_provider.dart b/apps/mobile/lib/core/providers/token_storage_provider.dart new file mode 100644 index 0000000..01c95de --- /dev/null +++ b/apps/mobile/lib/core/providers/token_storage_provider.dart @@ -0,0 +1,12 @@ +import 'package:flutter_riverpod/flutter_riverpod.dart'; +import 'package:flutter_secure_storage/flutter_secure_storage.dart'; + +import '../storage/secure_token_storage.dart'; + +final secureStorageProvider = Provider((ref) { + return const FlutterSecureStorage(); +}); + +final tokenStorageProvider = Provider((ref) { + return SecureTokenStorage(ref.read(secureStorageProvider)); +}); diff --git a/apps/mobile/lib/core/storage/database.dart b/apps/mobile/lib/core/storage/database.dart index 4367fd0..ff10836 100644 --- a/apps/mobile/lib/core/storage/database.dart +++ b/apps/mobile/lib/core/storage/database.dart @@ -1,4 +1,5 @@ import 'package:drift/drift.dart'; +import 'package:drift/native.dart'; import 'package:drift_flutter/drift_flutter.dart'; import 'daos/message_dao.dart'; @@ -29,6 +30,12 @@ part 'database.g.dart'; class AppDatabase extends _$AppDatabase { AppDatabase() : super(_openConnection()); + AppDatabase.forTesting(super.executor); + + factory AppDatabase.inMemory() { + return AppDatabase.forTesting(NativeDatabase.memory()); + } + @override int get schemaVersion => 1; } diff --git a/apps/mobile/lib/core/storage/secure_token_storage.dart b/apps/mobile/lib/core/storage/secure_token_storage.dart new file mode 100644 index 0000000..2b56450 --- /dev/null +++ b/apps/mobile/lib/core/storage/secure_token_storage.dart @@ -0,0 +1,28 @@ +import 'package:flutter_secure_storage/flutter_secure_storage.dart'; + +const String kBridgeToken = 'bridge_token'; + +/// Secure key-value storage for bridge pairing tokens. +/// +/// Backed by [FlutterSecureStorage] (Keychain on iOS, Keystore on Android). +class SecureTokenStorage { + const SecureTokenStorage(this._storage); + + final FlutterSecureStorage _storage; + + Future saveToken(String key, String value) async { + await _storage.write(key: key, value: value); + } + + Future getToken(String key) async { + return _storage.read(key: key); + } + + Future deleteToken(String key) async { + await _storage.delete(key: key); + } + + Future clearAll() async { + await _storage.deleteAll(); + } +} diff --git a/apps/mobile/lib/core/sync/sync_queue.dart b/apps/mobile/lib/core/sync/sync_queue.dart index 524a2b3..9d8832e 100644 --- a/apps/mobile/lib/core/sync/sync_queue.dart +++ b/apps/mobile/lib/core/sync/sync_queue.dart @@ -2,18 +2,20 @@ import 'dart:convert'; import 'package:drift/drift.dart'; +import '../network/connection_state.dart'; import '../network/websocket_messages.dart'; import '../network/websocket_service.dart'; import '../storage/daos/sync_dao.dart'; import '../storage/database.dart'; -import '../storage/tables/sync_queue_table.dart'; /// Manages an offline-first mutation queue backed by [SyncDao]. /// Operations enqueued while disconnected are replayed on reconnect via [flush]. class SyncQueueService { SyncQueueService({required AppDatabase database}) - : _dao = database.syncDao; + : _database = database, + _dao = database.syncDao; + final AppDatabase _database; final SyncDao _dao; Future enqueue( @@ -37,19 +39,21 @@ class SyncQueueService { final pending = await _dao.getPendingItems(); for (final item in pending) { try { - final payloadMap = - jsonDecode(item.payload) as Map; - final message = BridgeMessage( - type: BridgeMessageType.message, - timestamp: DateTime.now().toUtc(), - payload: { - 'operation': item.operation, - 'data': payloadMap, - if (item.sessionId != null) 'session_id': item.sessionId, - }, - ); - ws.send(message); + if (ws.currentStatus != ConnectionStatus.connected) { + await _dao.incrementRetry(item.id, 'Bridge unavailable'); + continue; + } + + final payloadMap = _decodePayload(item.payload); + final message = _buildMessage(item.operation, payloadMap); + final sent = ws.send(message); + if (!sent) { + await _dao.incrementRetry(item.id, 'Bridge unavailable'); + continue; + } + await _dao.markSynced(item.id); + await _markLocalArtifactsSynced(item.operation, payloadMap); } catch (e) { await _dao.incrementRetry(item.id, e.toString()); } @@ -60,4 +64,111 @@ class SyncQueueService { final items = await _dao.getPendingItems(); return items.length; } + + Map _decodePayload(String payload) { + return jsonDecode(payload) as Map; + } + + BridgeMessage _buildMessage( + String operation, + Map payload, + ) { + switch (operation) { + case 'message': + return BridgeMessage.message( + sessionId: payload['session_id'] as String? ?? '', + content: payload['content'] as String? ?? '', + role: payload['role'] as String? ?? 'user', + ); + case 'session_start': + return BridgeMessage.sessionStart( + agent: payload['agent'] as String? ?? 'claude-code', + sessionId: payload['session_id'] as String?, + workingDirectory: payload['working_directory'] as String? ?? '', + resume: payload['resume'] as bool? ?? false, + ); + case 'session_end': + return BridgeMessage.sessionEnd( + sessionId: payload['session_id'] as String? ?? '', + reason: payload['reason'] as String? ?? 'user_request', + ); + case 'approval_response': + return BridgeMessage.approvalResponse( + sessionId: payload['session_id'] as String? ?? '', + toolCallId: payload['tool_call_id'] as String? ?? '', + decision: payload['decision'] as String? ?? 'rejected', + modifications: payload['modifications'] as Map?, + ); + case 'notification_ack': + return BridgeMessage.notificationAck( + notificationIds: (payload['notification_ids'] as List? ?? []) + .whereType() + .toList(), + ); + } + + throw UnsupportedError('Unsupported sync queue operation: $operation'); + } + + Future _markLocalArtifactsSynced( + String operation, + Map payload, + ) async { + if (operation == 'message') { + final localMessageId = payload['local_message_id'] as String?; + if (localMessageId == null || localMessageId.isEmpty) { + return; + } + + final existingMessage = await (_database.select(_database.messages) + ..where((message) => message.id.equals(localMessageId))) + .getSingleOrNull(); + if (existingMessage == null) { + return; + } + + await _database.messageDao.updateMessage( + MessagesCompanion( + id: Value(existingMessage.id), + sessionId: Value(existingMessage.sessionId), + role: Value(existingMessage.role), + content: Value(existingMessage.content), + messageType: Value(existingMessage.messageType), + metadata: Value(existingMessage.metadata), + createdAt: Value(existingMessage.createdAt), + updatedAt: Value(DateTime.now().toUtc()), + synced: const Value(true), + ), + ); + return; + } + + if (operation == 'session_start') { + final sessionId = payload['session_id'] as String?; + if (sessionId == null || sessionId.isEmpty) { + return; + } + + final existingSession = await _database.sessionDao.getSession(sessionId); + if (existingSession == null) { + return; + } + + await _database.sessionDao.upsertSession( + SessionsCompanion( + id: Value(existingSession.id), + agentType: Value(existingSession.agentType), + agentId: Value(existingSession.agentId), + title: Value(existingSession.title), + workingDirectory: Value(existingSession.workingDirectory), + branch: Value(existingSession.branch), + status: Value(existingSession.status), + createdAt: Value(existingSession.createdAt), + lastMessageAt: Value(existingSession.lastMessageAt), + updatedAt: Value(DateTime.now().toUtc()), + synced: const Value(true), + ), + ); + } + } } From afcf92f156e3e098073963d30c69a6b7eb9353c3 Mon Sep 17 00:00:00 2001 From: MasuRii Date: Fri, 20 Mar 2026 12:56:10 +0800 Subject: [PATCH 16/22] feat(mobile): enhance chat functionality and tool rendering Expand chat provider with message handling and session management. Improve tool card widget with diff preview and approval actions. Enhance message bubbles and input bar with better UX. Refactor session list screen for improved navigation. - Expand chat_provider.dart with comprehensive state management - Enhance session_provider.dart with session lifecycle handling - Improve chat_screen.dart and session_list_screen.dart layouts - Update chat_input_bar.dart with send/retry controls - Enhance message_bubble.dart and message_part_widget.dart rendering - Extend tool_card.dart with diff preview and action buttons --- .../chat/domain/providers/chat_provider.dart | 618 +++++++++++++++--- .../domain/providers/session_provider.dart | 73 ++- .../presentation/screens/chat_screen.dart | 21 +- .../screens/session_list_screen.dart | 186 +++++- .../presentation/widgets/chat_input_bar.dart | 66 +- .../presentation/widgets/message_bubble.dart | 9 +- .../widgets/message_part_widget.dart | 20 +- .../chat/presentation/widgets/tool_card.dart | 257 ++++++-- 8 files changed, 1019 insertions(+), 231 deletions(-) diff --git a/apps/mobile/lib/features/chat/domain/providers/chat_provider.dart b/apps/mobile/lib/features/chat/domain/providers/chat_provider.dart index 8870965..7695a3f 100644 --- a/apps/mobile/lib/features/chat/domain/providers/chat_provider.dart +++ b/apps/mobile/lib/features/chat/domain/providers/chat_provider.dart @@ -1,3 +1,4 @@ +import 'dart:async'; import 'dart:convert'; import 'package:drift/drift.dart' show Value; @@ -7,13 +8,20 @@ import 'package:uuid/uuid.dart'; import '../../../../core/models/message_models.dart'; import '../../../../core/models/session_models.dart'; +import '../../../../core/network/connection_state.dart'; +import '../../../../core/network/websocket_messages.dart'; import '../../../../core/providers/database_provider.dart'; -import '../../../../core/network/bridge_socket.dart'; +import '../../../../core/providers/sync_queue_provider.dart'; +import '../../../../core/providers/websocket_provider.dart'; import '../../../../core/storage/database.dart' as db_lib; +import 'session_provider.dart'; part 'chat_provider.g.dart'; const _uuid = Uuid(); +const _messageOperation = 'message'; +const _sessionStartOperation = 'session_start'; +const _sessionEndOperation = 'session_end'; // --------------------------------------------------------------------------- // Streaming message buffer: sessionId → current streaming text @@ -74,36 +82,98 @@ Message _rowToDomainMessage(db_lib.Message row) { @riverpod class ChatNotifier extends _$ChatNotifier { + StreamSubscription? _messageSubscription; + StreamSubscription? _statusSubscription; + @override Future build() async { - final socket = ref.watch(bridgeSocketProvider); - socket.messageStream.listen(_handleBridgeMessage); + final service = ref.watch(webSocketServiceProvider); + final syncQueue = ref.watch(syncQueueServiceProvider); + + final cachedAckPayload = service.lastConnectionAckPayload; + if (cachedAckPayload != null) { + await _syncActiveSessions(cachedAckPayload); + } + if (service.currentStatus == ConnectionStatus.connected) { + await syncQueue.flush(service); + } + + _messageSubscription = service.messages.listen(_handleBridgeMessage); + _statusSubscription = service.connectionStatus.listen((status) async { + if (status == ConnectionStatus.connected) { + await syncQueue.flush(service); + final ackPayload = service.lastConnectionAckPayload; + if (ackPayload != null) { + await _syncActiveSessions(ackPayload); + } + } + }); + + ref.onDispose(() { + _messageSubscription?.cancel(); + _statusSubscription?.cancel(); + }); } - void _handleBridgeMessage(Map msg) { - final type = msg['type'] as String?; - final sessionId = msg['session_id'] as String? ?? ''; - - switch (type) { - case 'stream_start': - _setStreaming(sessionId, ''); - case 'stream_chunk': - final chunk = msg['chunk'] as String? ?? ''; - _appendStreaming(sessionId, chunk); - case 'stream_end': - _finalizeStreaming(sessionId); - case 'tool_call': - _persistToolCall(sessionId, msg); - case 'tool_result': - _persistToolResult(sessionId, msg); - case 'session_ready': - _onSessionReady(sessionId, msg); + void _handleBridgeMessage(BridgeMessage message) { + final payload = message.payload; + + switch (message.type) { + case BridgeMessageType.connectionAck: + unawaited(_syncActiveSessions(payload)); + break; + case BridgeMessageType.sessionReady: + unawaited(_persistSessionReady(payload)); + break; + case BridgeMessageType.streamStart: + _setStreaming(_stringValue(payload['session_id']), ''); + break; + case BridgeMessageType.streamChunk: + _appendStreaming( + _stringValue(payload['session_id']), + _stringValue(payload['content']), + ); + break; + case BridgeMessageType.streamEnd: + unawaited(_finalizeStreaming(_stringValue(payload['session_id']))); + break; + case BridgeMessageType.approvalRequired: + unawaited(_persistApprovalRequired(payload)); + break; + case BridgeMessageType.toolResult: + unawaited(_persistToolResult(payload)); + break; + case BridgeMessageType.claudeEvent: + unawaited(_handleClaudeEvent(payload)); + break; + case BridgeMessageType.sessionEnd: + unawaited(_markSessionClosed(_stringValue(payload['session_id']))); + break; default: break; } } + Future _syncActiveSessions(Map payload) async { + final rawSessions = payload['active_sessions'] as List? ?? []; + for (final rawSession in rawSessions.whereType>()) { + await _upsertSession( + sessionId: _stringValue(rawSession['session_id']), + agentType: _stringValue(rawSession['agent'], fallback: 'claude-code'), + title: _stringValue(rawSession['title']), + workingDirectory: _stringValue(rawSession['working_directory']), + status: _sessionStatusFromRemote(rawSession['status'] as String?), + synced: true, + ); + } + ref.invalidate(activeSessionsProvider); + } + void _setStreaming(String sessionId, String text) { + if (sessionId.isEmpty) { + return; + } + final current = Map.from( ref.read(streamingMessageProvider), ); @@ -112,6 +182,10 @@ class ChatNotifier extends _$ChatNotifier { } void _appendStreaming(String sessionId, String chunk) { + if (sessionId.isEmpty || chunk.isEmpty) { + return; + } + final current = Map.from( ref.read(streamingMessageProvider), ); @@ -120,16 +194,24 @@ class ChatNotifier extends _$ChatNotifier { } Future _finalizeStreaming(String sessionId) async { + if (sessionId.isEmpty) { + return; + } + final current = Map.from( ref.read(streamingMessageProvider), ); final text = current.remove(sessionId) ?? ''; ref.read(streamingMessageProvider.notifier).state = current; - if (text.isNotEmpty) { - final db = ref.read(databaseProvider); - final now = DateTime.now(); - await db.messageDao.insertMessage(_toCompanion(Message( + if (text.isEmpty) { + return; + } + + await _ensureSessionExists(sessionId); + final now = DateTime.now().toUtc(); + await _insertMessage( + Message( id: _uuid.v4(), sessionId: sessionId, role: MessageRole.agent, @@ -138,104 +220,393 @@ class ChatNotifier extends _$ChatNotifier { parts: [MessagePart.text(content: text)], createdAt: now, updatedAt: now, - ))); + ), + ); + } + + Future _persistSessionReady(Map payload) async { + final sessionId = _stringValue(payload['session_id']); + if (sessionId.isEmpty) { + return; } + + await _upsertSession( + sessionId: sessionId, + agentType: _stringValue(payload['agent'], fallback: 'claude-code'), + title: _titleFromWorkingDirectory( + _stringValue(payload['working_directory']), + ), + workingDirectory: _stringValue(payload['working_directory']), + branch: payload['branch'] as String?, + status: SessionStatus.active, + synced: true, + ); + ref.invalidate(activeSessionsProvider); } - Future _persistToolCall( - String sessionId, Map msg) async { + Future _persistApprovalRequired(Map payload) async { + final sessionId = _stringValue(payload['session_id']); + if (sessionId.isEmpty) { + return; + } + + await _ensureSessionExists(sessionId); + final now = DateTime.now().toUtc(); + await _insertMessage( + Message( + id: _uuid.v4(), + sessionId: sessionId, + role: MessageRole.agent, + content: _stringValue(payload['description']), + type: MessageType.toolCall, + parts: [ + MessagePart.toolUse( + tool: _stringValue(payload['tool'], fallback: 'unknown_tool'), + params: _mapValue(payload['params']), + id: _stringValue(payload['tool_call_id']), + ), + ], + metadata: { + 'description': _stringValue(payload['description']), + 'risk_level': _stringValue(payload['risk_level']), + 'source': _stringValue(payload['source']), + }, + createdAt: now, + updatedAt: now, + ), + ); + } + + Future _persistToolResult(Map payload) async { + final sessionId = _stringValue(payload['session_id']); + if (sessionId.isEmpty) { + return; + } + + await _ensureSessionExists(sessionId); + final resultMap = _mapValue(payload['result']); + final toolName = _stringValue(payload['tool'], fallback: 'unknown_tool'); + final metadata = {'tool': toolName}; + final diff = resultMap['diff'] as String?; + if (diff != null && diff.isNotEmpty) { + metadata['diff'] = diff; + } + + final now = DateTime.now().toUtc(); + await _insertMessage( + Message( + id: _uuid.v4(), + sessionId: sessionId, + role: MessageRole.agent, + content: _stringValue(resultMap['content']), + type: MessageType.toolResult, + parts: [ + MessagePart.toolResult( + toolCallId: _stringValue(payload['tool_call_id']), + result: ToolResult( + success: resultMap['success'] as bool? ?? true, + content: _stringValue(resultMap['content']), + metadata: metadata, + error: resultMap['error'] as String?, + durationMs: resultMap['duration_ms'] as int?, + ), + ), + ], + createdAt: now, + updatedAt: now, + ), + ); + } + + Future _handleClaudeEvent(Map payload) async { + final eventType = _stringValue(payload['event_type']); + final sessionId = _stringValue(payload['session_id']); + final eventPayload = _mapValue(payload['payload']); + + if (sessionId.isEmpty || eventType.isEmpty) { + return; + } + + switch (eventType) { + case 'SessionStart': + await _ensureSessionExists( + sessionId, + workingDirectory: _stringValue(eventPayload['working_directory']), + title: _stringValue(eventPayload['title']), + ); + ref.invalidate(activeSessionsProvider); + break; + case 'UserPromptSubmit': + final content = _stringValue( + eventPayload['prompt'], + fallback: _stringValue( + eventPayload['message'], + fallback: _stringValue(eventPayload['text']), + ), + ); + if (content.isEmpty) { + break; + } + await _ensureSessionExists(sessionId); + final now = DateTime.now().toUtc(); + await _insertMessage( + Message( + id: _uuid.v4(), + sessionId: sessionId, + role: MessageRole.user, + content: content, + type: MessageType.text, + parts: [MessagePart.text(content: content)], + createdAt: now, + updatedAt: now, + ), + ); + break; + case 'SessionEnd': + case 'Stop': + await _markSessionClosed(sessionId); + break; + default: + break; + } + } + + Future _ensureSessionExists( + String sessionId, { + String? workingDirectory, + String? title, + }) async { final db = ref.read(databaseProvider); - final toolName = msg['tool'] as String? ?? 'unknown'; - final params = - (msg['params'] as Map?) ?? {}; - final id = msg['id'] as String? ?? _uuid.v4(); - final now = DateTime.now(); - - await db.messageDao.insertMessage(_toCompanion(Message( - id: _uuid.v4(), + final existing = await db.sessionDao.getSession(sessionId); + if (existing != null) { + return; + } + + await _upsertSession( sessionId: sessionId, - role: MessageRole.agent, - content: '', - type: MessageType.toolCall, - parts: [MessagePart.toolUse(tool: toolName, params: params, id: id)], - createdAt: now, - updatedAt: now, - ))); + agentType: 'claude-code', + title: title ?? _titleFromWorkingDirectory(workingDirectory ?? ''), + workingDirectory: workingDirectory ?? '', + status: SessionStatus.active, + synced: true, + ); } - Future _persistToolResult( - String sessionId, Map msg) async { + Future _upsertSession({ + required String sessionId, + required String agentType, + required String title, + required String workingDirectory, + String? branch, + required SessionStatus status, + required bool synced, + }) async { + if (sessionId.isEmpty) { + return; + } + final db = ref.read(databaseProvider); - final toolCallId = msg['tool_call_id'] as String? ?? ''; - final success = msg['success'] as bool? ?? true; - final content = msg['content'] as String? ?? ''; - final now = DateTime.now(); + final existing = await db.sessionDao.getSession(sessionId); + final now = DateTime.now().toUtc(); - await db.messageDao.insertMessage(_toCompanion(Message( - id: _uuid.v4(), - sessionId: sessionId, - role: MessageRole.agent, - content: '', - type: MessageType.toolResult, - parts: [ - MessagePart.toolResult( - toolCallId: toolCallId, - result: ToolResult(success: success, content: content), - ) - ], - createdAt: now, - updatedAt: now, - ))); + await db.sessionDao.upsertSession( + db_lib.SessionsCompanion( + id: Value(sessionId), + agentType: Value(existing?.agentType ?? agentType), + agentId: Value(existing?.agentId), + title: Value( + _coalesceNonEmpty( + existing?.title, + title, + _titleFromWorkingDirectory(workingDirectory), + ), + ), + workingDirectory: Value( + _coalesceNonEmpty(existing?.workingDirectory, workingDirectory), + ), + branch: Value(branch ?? existing?.branch), + status: Value(status.name), + createdAt: Value(existing?.createdAt ?? now), + lastMessageAt: Value(existing?.lastMessageAt), + updatedAt: Value(now), + synced: Value((existing?.synced ?? false) || synced), + ), + ); + } + + Future _touchSession(String sessionId) async { + final db = ref.read(databaseProvider); + final existing = await db.sessionDao.getSession(sessionId); + if (existing == null) { + return; + } + + final now = DateTime.now().toUtc(); + await db.sessionDao.upsertSession( + db_lib.SessionsCompanion( + id: Value(existing.id), + agentType: Value(existing.agentType), + agentId: Value(existing.agentId), + title: Value(existing.title), + workingDirectory: Value(existing.workingDirectory), + branch: Value(existing.branch), + status: Value(existing.status), + createdAt: Value(existing.createdAt), + lastMessageAt: Value(now), + updatedAt: Value(now), + synced: Value(existing.synced), + ), + ); + ref.invalidate(activeSessionsProvider); } - void _onSessionReady(String sessionId, Map msg) { - // Session is live; any UI waiting can react via activeSessionsProvider + Future _markSessionClosed(String sessionId) async { + if (sessionId.isEmpty) { + return; + } + + final db = ref.read(databaseProvider); + final existing = await db.sessionDao.getSession(sessionId); + if (existing == null) { + return; + } + + final now = DateTime.now().toUtc(); + await db.sessionDao.upsertSession( + db_lib.SessionsCompanion( + id: Value(existing.id), + agentType: Value(existing.agentType), + agentId: Value(existing.agentId), + title: Value(existing.title), + workingDirectory: Value(existing.workingDirectory), + branch: Value(existing.branch), + status: Value(SessionStatus.closed.name), + createdAt: Value(existing.createdAt), + lastMessageAt: Value(existing.lastMessageAt), + updatedAt: Value(now), + synced: Value(existing.synced), + ), + ); + ref.invalidate(activeSessionsProvider); + } + + Future _insertMessage(Message message) async { + final db = ref.read(databaseProvider); + await db.messageDao.insertMessage(_toCompanion(message)); + await _touchSession(message.sessionId); } // ---------- Public actions ----------------------------------------------- Future sendMessage(String sessionId, String content) async { - if (content.trim().isEmpty) return; - final db = ref.read(databaseProvider); + final trimmedContent = content.trim(); + if (trimmedContent.isEmpty) { + return; + } + + await _ensureSessionExists(sessionId); - // Optimistic insert - final now = DateTime.now(); - final msg = Message( - id: _uuid.v4(), + final service = ref.read(webSocketServiceProvider); + final syncQueue = ref.read(syncQueueServiceProvider); + final now = DateTime.now().toUtc(); + final localMessageId = _uuid.v4(); + final outgoingMessage = BridgeMessage.message( sessionId: sessionId, - role: MessageRole.user, - content: content, - type: MessageType.text, - parts: [MessagePart.text(content: content)], - createdAt: now, - updatedAt: now, - synced: false, + content: trimmedContent, ); - await db.messageDao.insertMessage(_toCompanion(msg)); - - // Send over socket - final socket = ref.read(bridgeSocketProvider); - socket.send({ - 'type': 'user_message', - 'session_id': sessionId, - 'content': content, - }); + final sent = service.send(outgoingMessage); + + await _insertMessage( + Message( + id: localMessageId, + sessionId: sessionId, + role: MessageRole.user, + content: trimmedContent, + type: MessageType.text, + parts: [MessagePart.text(content: trimmedContent)], + createdAt: now, + updatedAt: now, + synced: sent, + ), + ); + + if (!sent) { + await syncQueue.enqueue( + _messageOperation, + { + 'session_id': sessionId, + 'content': trimmedContent, + 'role': 'user', + 'local_message_id': localMessageId, + }, + sessionId: sessionId, + ); + } } - Future startSession(String agentId, String workingDir) async { - final socket = ref.read(bridgeSocketProvider); + Future startSession(String agent, String workingDir) async { + final normalizedDirectory = workingDir.trim(); + if (normalizedDirectory.isEmpty) { + throw ArgumentError('Working directory is required.'); + } + final sessionId = _uuid.v4(); - socket.send({ - 'type': 'session_start', - 'session_id': sessionId, - 'agent_id': agentId, - 'working_directory': workingDir, - }); + final service = ref.read(webSocketServiceProvider); + final syncQueue = ref.read(syncQueueServiceProvider); + final sent = service.send( + BridgeMessage.sessionStart( + agent: agent, + sessionId: sessionId, + workingDirectory: normalizedDirectory, + ), + ); + + await _upsertSession( + sessionId: sessionId, + agentType: agent, + title: _titleFromWorkingDirectory(normalizedDirectory), + workingDirectory: normalizedDirectory, + status: SessionStatus.active, + synced: sent, + ); + + if (!sent) { + await syncQueue.enqueue( + _sessionStartOperation, + { + 'agent': agent, + 'session_id': sessionId, + 'working_directory': normalizedDirectory, + 'resume': false, + }, + sessionId: sessionId, + ); + } + + ref.invalidate(activeSessionsProvider); + return sessionId; } Future endSession(String sessionId) async { - final socket = ref.read(bridgeSocketProvider); - socket.send({'type': 'session_end', 'session_id': sessionId}); + if (sessionId.isEmpty) { + return; + } + + final service = ref.read(webSocketServiceProvider); + final syncQueue = ref.read(syncQueueServiceProvider); + final sent = service.send( + BridgeMessage.sessionEnd(sessionId: sessionId), + ); + + if (!sent) { + await syncQueue.enqueue( + _sessionEndOperation, + {'session_id': sessionId, 'reason': 'user_request'}, + sessionId: sessionId, + ); + } + + await _markSessionClosed(sessionId); } } @@ -260,3 +631,54 @@ db_lib.MessagesCompanion _toCompanion(Message msg) { synced: Value(msg.synced), ); } + +String _stringValue(Object? value, {String fallback = ''}) { + if (value is String && value.isNotEmpty) { + return value; + } + return fallback; +} + +Map _mapValue(Object? value) { + if (value is Map) { + return value; + } + if (value is Map) { + return value.map( + (key, value) => MapEntry(key.toString(), value), + ); + } + return {}; +} + +String _titleFromWorkingDirectory(String workingDirectory) { + if (workingDirectory.isEmpty) { + return 'Claude Code'; + } + + final normalized = workingDirectory.replaceAll('\\', '/'); + final segments = normalized.split('/').where((segment) => segment.isNotEmpty); + return segments.isEmpty ? workingDirectory : segments.last; +} + +String _coalesceNonEmpty(String? first, String? second, + [String fallback = '']) { + if (first != null && first.isNotEmpty) { + return first; + } + if (second != null && second.isNotEmpty) { + return second; + } + return fallback; +} + +SessionStatus _sessionStatusFromRemote(String? status) { + switch (status) { + case 'closed': + return SessionStatus.closed; + case 'paused': + return SessionStatus.paused; + default: + return SessionStatus.active; + } +} diff --git a/apps/mobile/lib/features/chat/domain/providers/session_provider.dart b/apps/mobile/lib/features/chat/domain/providers/session_provider.dart index 4430715..d0df4f2 100644 --- a/apps/mobile/lib/features/chat/domain/providers/session_provider.dart +++ b/apps/mobile/lib/features/chat/domain/providers/session_provider.dart @@ -1,9 +1,13 @@ +import 'dart:async'; + +import 'package:drift/drift.dart' show Value; import 'package:flutter_riverpod/flutter_riverpod.dart'; import 'package:riverpod_annotation/riverpod_annotation.dart'; import '../../../../core/models/session_models.dart'; +import '../../../../core/network/websocket_messages.dart'; import '../../../../core/providers/database_provider.dart'; -import '../../../../core/network/bridge_socket.dart'; +import '../../../../core/providers/websocket_provider.dart'; import '../../../../core/storage/database.dart' as db_lib; part 'session_provider.g.dart'; @@ -20,21 +24,33 @@ final currentSessionProvider = StateProvider((ref) => null); @riverpod class ActiveSessions extends _$ActiveSessions { + StreamSubscription? _messageSubscription; + @override Future> build() async { final db = ref.watch(databaseProvider); - final rows = await db.sessionDao.watchAllSessions().first; - final sessions = rows.map(_rowToChatSession).toList(); + final service = ref.watch(webSocketServiceProvider); + + final cachedAckPayload = service.lastConnectionAckPayload; + if (cachedAckPayload != null) { + await _syncRemoteSessions(cachedAckPayload); + } - // Keep up-to-date when bridge sends session events - final socket = ref.watch(bridgeSocketProvider); - socket.messageStream.listen((msg) { - if (msg['type'] == 'session_ready' || msg['type'] == 'session_closed') { + _messageSubscription = service.messages.listen((message) { + if (message.type == BridgeMessageType.connectionAck) { + unawaited(_syncRemoteSessions(message.payload).then((_) { + ref.invalidateSelf(); + })); + } + if (message.type == BridgeMessageType.sessionReady || + message.type == BridgeMessageType.sessionEnd) { ref.invalidateSelf(); } }); + ref.onDispose(() => _messageSubscription?.cancel()); - return sessions; + final rows = await db.sessionDao.watchAllSessions().first; + return rows.map(_rowToChatSession).toList(); } Future refresh() async { @@ -46,6 +62,40 @@ class ActiveSessions extends _$ActiveSessions { await db.sessionDao.deleteSession(sessionId); ref.invalidateSelf(); } + + Future _syncRemoteSessions(Map payload) async { + final db = ref.read(databaseProvider); + final rawSessions = payload['active_sessions'] as List? ?? []; + for (final rawSession in rawSessions.whereType>()) { + final sessionId = rawSession['session_id'] as String?; + if (sessionId == null || sessionId.isEmpty) { + continue; + } + + final existing = await db.sessionDao.getSession(sessionId); + final now = DateTime.now().toUtc(); + await db.sessionDao.upsertSession( + db_lib.SessionsCompanion( + id: Value(sessionId), + agentType: Value(rawSession['agent'] as String? ?? 'claude-code'), + agentId: Value(existing?.agentId), + title: Value(_title(rawSession['title'] as String?)), + workingDirectory: + Value(rawSession['working_directory'] as String? ?? ''), + branch: Value(existing?.branch), + status: Value( + (rawSession['status'] as String?) == 'closed' + ? SessionStatus.closed.name + : SessionStatus.active.name, + ), + createdAt: Value(existing?.createdAt ?? now), + lastMessageAt: Value(existing?.lastMessageAt), + updatedAt: Value(now), + synced: const Value(true), + ), + ); + } + } } // --------------------------------------------------------------------------- @@ -84,3 +134,10 @@ ChatSession _rowToChatSession(db_lib.Session row) { synced: row.synced, ); } + +String _title(String? value) { + if (value != null && value.isNotEmpty) { + return value; + } + return 'Claude Code'; +} diff --git a/apps/mobile/lib/features/chat/presentation/screens/chat_screen.dart b/apps/mobile/lib/features/chat/presentation/screens/chat_screen.dart index bb5e77e..948da1a 100644 --- a/apps/mobile/lib/features/chat/presentation/screens/chat_screen.dart +++ b/apps/mobile/lib/features/chat/presentation/screens/chat_screen.dart @@ -59,13 +59,15 @@ class _ChatScreenState extends ConsumerState { @override Widget build(BuildContext context) { + ref.watch(chatNotifierProvider); final session = ref.watch(activeSessionProvider(widget.sessionId)); final messagesAsync = ref.watch(messagesProvider(widget.sessionId)); final streamingMap = ref.watch(streamingMessageProvider); final streamingText = streamingMap[widget.sessionId]; // Auto-scroll when messages change - ref.listen(messagesProvider(widget.sessionId), (_, __) => _scrollToBottom()); + ref.listen( + messagesProvider(widget.sessionId), (_, __) => _scrollToBottom()); return LayoutBuilder( builder: (context, constraints) { @@ -74,12 +76,13 @@ class _ChatScreenState extends ConsumerState { if (isTablet) { return Row( children: [ - SizedBox( + const SizedBox( width: 300, - child: const SessionListScreen(), + child: SessionListScreen(), ), const VerticalDivider(width: 1, color: Color(0xFF3C3C3C)), - Expanded(child: _ChatBody( + Expanded( + child: _ChatBody( sessionId: widget.sessionId, sessionTitle: session?.title ?? 'Chat', branch: session?.branch, @@ -155,7 +158,8 @@ class _ChatBody extends StatelessWidget { child: Row( mainAxisSize: MainAxisSize.min, children: [ - const Icon(Icons.call_split, size: 12, color: Color(0xFF4EC9B0)), + const Icon(Icons.call_split, + size: 12, color: Color(0xFF4EC9B0)), const SizedBox(width: 4), Text( branch!, @@ -178,7 +182,8 @@ class _ChatBody extends StatelessWidget { style: const TextStyle(color: Colors.redAccent)), ), data: (messages) { - final hasStreaming = streamingText != null && streamingText!.isNotEmpty; + final hasStreaming = + streamingText != null && streamingText!.isNotEmpty; final itemCount = messages.length + (hasStreaming ? 1 : 0); if (itemCount == 0) { @@ -192,8 +197,8 @@ class _ChatBody extends StatelessWidget { return ListView.builder( controller: scrollController, - padding: const EdgeInsets.symmetric( - horizontal: 12, vertical: 8), + padding: + const EdgeInsets.symmetric(horizontal: 12, vertical: 8), itemCount: itemCount, itemBuilder: (context, i) { if (i < messages.length) { diff --git a/apps/mobile/lib/features/chat/presentation/screens/session_list_screen.dart b/apps/mobile/lib/features/chat/presentation/screens/session_list_screen.dart index e57febb..950ea31 100644 --- a/apps/mobile/lib/features/chat/presentation/screens/session_list_screen.dart +++ b/apps/mobile/lib/features/chat/presentation/screens/session_list_screen.dart @@ -4,6 +4,9 @@ import 'package:go_router/go_router.dart'; import 'package:intl/intl.dart'; import '../../../../core/models/session_models.dart'; +import '../../../../core/network/connection_state.dart'; +import '../../../../core/providers/bridge_provider.dart'; +import '../../domain/providers/chat_provider.dart'; import '../../domain/providers/session_provider.dart'; class SessionListScreen extends ConsumerWidget { @@ -11,6 +14,7 @@ class SessionListScreen extends ConsumerWidget { @override Widget build(BuildContext context, WidgetRef ref) { + ref.watch(chatNotifierProvider); final sessionsAsync = ref.watch(activeSessionsProvider); return Scaffold( @@ -20,14 +24,13 @@ class SessionListScreen extends ConsumerWidget { title: const Text('Sessions'), ), floatingActionButton: FloatingActionButton.extended( - onPressed: () => _showAgentPicker(context, ref), + onPressed: () => _showNewSessionSheet(context, ref), backgroundColor: const Color(0xFF569CD6), icon: const Icon(Icons.add), label: const Text('New Session'), ), body: sessionsAsync.when( - loading: () => - const Center(child: CircularProgressIndicator()), + loading: () => const Center(child: CircularProgressIndicator()), error: (e, _) => Center( child: Text( 'Error: $e', @@ -38,20 +41,20 @@ class SessionListScreen extends ConsumerWidget { if (sessions.isEmpty) { return const Center( child: Text( - 'No active sessions.\nTap + to start one.', + 'No sessions yet.\nTap + to start a Claude Code Agent SDK session.', textAlign: TextAlign.center, style: TextStyle(color: Colors.grey), ), ); } return RefreshIndicator( - onRefresh: () => ref.read(activeSessionsProvider.notifier).refresh(), + onRefresh: () => + ref.read(activeSessionsProvider.notifier).refresh(), child: ListView.separated( padding: const EdgeInsets.all(8), itemCount: sessions.length, separatorBuilder: (_, __) => const SizedBox(height: 4), - itemBuilder: (context, i) => - _SessionTile(session: sessions[i]), + itemBuilder: (context, i) => _SessionTile(session: sessions[i]), ), ); }, @@ -59,15 +62,21 @@ class SessionListScreen extends ConsumerWidget { ); } - void _showAgentPicker(BuildContext context, WidgetRef ref) { - showModalBottomSheet( + Future _showNewSessionSheet(BuildContext context, WidgetRef ref) async { + final sessionId = await showModalBottomSheet( context: context, + isScrollControlled: true, backgroundColor: const Color(0xFF252526), shape: const RoundedRectangleBorder( borderRadius: BorderRadius.vertical(top: Radius.circular(16)), ), - builder: (_) => const _AgentPickerSheet(), + builder: (_) => const _NewSessionSheet(), ); + + if (sessionId != null && context.mounted) { + ref.read(currentSessionProvider.notifier).state = sessionId; + context.go('/home/chat/$sessionId'); + } } } @@ -99,19 +108,26 @@ class _SessionTile extends ConsumerWidget { ), ), title: Text( - session.title.isNotEmpty ? session.title : 'Session ${session.id.substring(0, 8)}', + session.title.isNotEmpty + ? session.title + : 'Session ${session.id.substring(0, 8)}', style: const TextStyle(color: Colors.white), overflow: TextOverflow.ellipsis, ), subtitle: Text( - session.workingDirectory, + session.workingDirectory.isEmpty + ? 'Waiting for bridge details' + : session.workingDirectory, style: const TextStyle(color: Colors.grey, fontSize: 12), overflow: TextOverflow.ellipsis, ), trailing: Row( mainAxisSize: MainAxisSize.min, children: [ - Text(timeLabel, style: const TextStyle(color: Colors.grey, fontSize: 12)), + Text( + timeLabel, + style: const TextStyle(color: Colors.grey, fontSize: 12), + ), const SizedBox(width: 8), Container( width: 8, @@ -136,9 +152,14 @@ class _SessionTile extends ConsumerWidget { context: context, builder: (_) => AlertDialog( backgroundColor: const Color(0xFF252526), - title: const Text('Delete Session', style: TextStyle(color: Colors.white)), - content: const Text('Remove this session and all its messages?', - style: TextStyle(color: Colors.grey)), + title: const Text( + 'Delete Session', + style: TextStyle(color: Colors.white), + ), + content: const Text( + 'Remove this session and all its messages?', + style: TextStyle(color: Colors.grey), + ), actions: [ TextButton( onPressed: () => Navigator.pop(context, false), @@ -146,7 +167,10 @@ class _SessionTile extends ConsumerWidget { ), TextButton( onPressed: () => Navigator.pop(context, true), - child: const Text('Delete', style: TextStyle(color: Colors.redAccent)), + child: const Text( + 'Delete', + style: TextStyle(color: Colors.redAccent), + ), ), ], ), @@ -157,34 +181,128 @@ class _SessionTile extends ConsumerWidget { } } -class _AgentPickerSheet extends ConsumerWidget { - const _AgentPickerSheet(); +class _NewSessionSheet extends ConsumerStatefulWidget { + const _NewSessionSheet(); @override - Widget build(BuildContext context, WidgetRef ref) { + ConsumerState<_NewSessionSheet> createState() => _NewSessionSheetState(); +} + +class _NewSessionSheetState extends ConsumerState<_NewSessionSheet> { + final TextEditingController _workingDirectoryController = + TextEditingController(); + bool _submitting = false; + String? _error; + + @override + void dispose() { + _workingDirectoryController.dispose(); + super.dispose(); + } + + Future _startSession() async { + final workingDirectory = _workingDirectoryController.text.trim(); + if (workingDirectory.isEmpty) { + setState(() { + _error = 'Working directory is required.'; + }); + return; + } + + setState(() { + _submitting = true; + _error = null; + }); + + try { + final sessionId = await ref + .read(chatNotifierProvider.notifier) + .startSession('claude-code', workingDirectory); + if (mounted) { + Navigator.of(context).pop(sessionId); + } + } catch (error) { + if (!mounted) { + return; + } + setState(() { + _submitting = false; + _error = error.toString(); + }); + } + } + + @override + Widget build(BuildContext context) { + final bridgeStatus = ref.watch(bridgeProvider); + final isConnected = bridgeStatus == ConnectionStatus.connected; + return Padding( - padding: const EdgeInsets.all(24), + padding: EdgeInsets.only( + left: 24, + right: 24, + top: 24, + bottom: MediaQuery.of(context).viewInsets.bottom + 24, + ), child: Column( mainAxisSize: MainAxisSize.min, crossAxisAlignment: CrossAxisAlignment.stretch, children: [ const Text( - 'Pick Agent Type', - style: TextStyle(color: Colors.white, fontSize: 18, fontWeight: FontWeight.bold), + 'Start Claude Code Session', + style: TextStyle( + color: Colors.white, + fontSize: 18, + fontWeight: FontWeight.bold, + ), + ), + const SizedBox(height: 12), + Text( + isConnected + ? 'This starts a parallel Agent SDK session on the connected bridge.' + : 'Bridge is offline. The session start request will queue locally and send after reconnect.', + style: TextStyle( + color: isConnected ? const Color(0xFF9CDCFE) : Colors.orange, + ), ), const SizedBox(height: 16), - const Text( - 'Connect a bridge agent first from Settings → Agents.', - style: TextStyle(color: Colors.grey), + TextField( + key: const Key('newSessionWorkingDirectoryField'), + controller: _workingDirectoryController, + style: const TextStyle(color: Colors.white), + decoration: InputDecoration( + labelText: 'Working Directory', + labelStyle: const TextStyle(color: Color(0xFF9CDCFE)), + hintText: '/Users/me/project', + hintStyle: const TextStyle(color: Colors.grey), + filled: true, + fillColor: const Color(0xFF1E1E1E), + border: OutlineInputBorder( + borderRadius: BorderRadius.circular(8), + borderSide: BorderSide.none, + ), + ), + textInputAction: TextInputAction.done, + onSubmitted: (_) => _submitting ? null : _startSession(), ), - const SizedBox(height: 24), - TextButton( - onPressed: () { - Navigator.pop(context); - context.go('/settings/agents'); - }, - child: const Text('Go to Agent Settings', - style: TextStyle(color: Color(0xFF569CD6))), + if (_error != null) ...[ + const SizedBox(height: 12), + Text( + _error!, + style: const TextStyle(color: Colors.redAccent), + ), + ], + const SizedBox(height: 20), + FilledButton.icon( + onPressed: _submitting ? null : _startSession, + icon: _submitting + ? const SizedBox( + width: 16, + height: 16, + child: CircularProgressIndicator(strokeWidth: 2), + ) + : Icon(isConnected ? Icons.play_arrow : Icons.schedule_send), + label: Text(isConnected ? 'Start Session' : 'Queue Session Start'), ), ], ), diff --git a/apps/mobile/lib/features/chat/presentation/widgets/chat_input_bar.dart b/apps/mobile/lib/features/chat/presentation/widgets/chat_input_bar.dart index 8515089..d8c95e9 100644 --- a/apps/mobile/lib/features/chat/presentation/widgets/chat_input_bar.dart +++ b/apps/mobile/lib/features/chat/presentation/widgets/chat_input_bar.dart @@ -27,8 +27,10 @@ class _ChatInputBarState extends ConsumerState { void initState() { super.initState(); _controller.addListener(() { - final newHasText = _controller.text.isNotEmpty; - if (newHasText != _hasText) setState(() => _hasText = newHasText); + final newHasText = _controller.text.trim().isNotEmpty; + if (newHasText != _hasText) { + setState(() => _hasText = newHasText); + } }); } @@ -40,15 +42,18 @@ class _ChatInputBarState extends ConsumerState { void _send() { final text = _controller.text.trim(); - if (text.isEmpty) return; + if (text.isEmpty) { + return; + } _controller.clear(); widget.onSend(text); } @override Widget build(BuildContext context) { - final socketState = ref.watch(bridgeSocketStateProvider); - final isConnected = socketState == BridgeSocketState.connected; + final socketState = ref.watch(bridgeSocketStateProvider).valueOrNull; + final isConnected = socketState == ConnectionStatus.connected; + final isReconnecting = socketState == ConnectionStatus.reconnecting; return Container( color: const Color(0xFF252526), @@ -59,17 +64,26 @@ class _ChatInputBarState extends ConsumerState { if (!isConnected) Container( width: double.infinity, - padding: - const EdgeInsets.symmetric(horizontal: 12, vertical: 4), - color: Colors.orange.withOpacity(0.15), - child: const Row( - mainAxisSize: MainAxisSize.min, + padding: const EdgeInsets.symmetric(horizontal: 12, vertical: 4), + color: Colors.orange.withValues(alpha: 0.15), + child: Row( children: [ - Icon(Icons.wifi_off, size: 12, color: Colors.orange), - SizedBox(width: 6), - Text( - 'Offline — reconnecting…', - style: TextStyle(color: Colors.orange, fontSize: 12), + Icon( + isReconnecting ? Icons.wifi_find : Icons.wifi_off, + size: 12, + color: Colors.orange, + ), + const SizedBox(width: 6), + Expanded( + child: Text( + isReconnecting + ? 'Reconnecting — messages will queue locally' + : 'Offline — messages will send when reconnected', + style: const TextStyle( + color: Colors.orange, + fontSize: 12, + ), + ), ), ], ), @@ -101,7 +115,9 @@ class _ChatInputBarState extends ConsumerState { filled: true, fillColor: const Color(0xFF3C3C3C), contentPadding: const EdgeInsets.symmetric( - horizontal: 12, vertical: 8), + horizontal: 12, + vertical: 8, + ), border: OutlineInputBorder( borderRadius: BorderRadius.circular(8), borderSide: BorderSide.none, @@ -110,7 +126,9 @@ class _ChatInputBarState extends ConsumerState { ? '${_controller.text.length} chars' : null, counterStyle: const TextStyle( - color: Colors.grey, fontSize: 11), + color: Colors.grey, + fontSize: 11, + ), ), textInputAction: TextInputAction.newline, ), @@ -118,15 +136,19 @@ class _ChatInputBarState extends ConsumerState { ), const SizedBox(width: 4), AnimatedOpacity( - opacity: (_hasText && isConnected) ? 1.0 : 0.4, + opacity: _hasText ? 1.0 : 0.4, duration: const Duration(milliseconds: 150), child: Semantics( - label: 'Send message', + label: isConnected ? 'Send message' : 'Queue message', button: true, child: IconButton( - icon: const Icon(Icons.send, color: Color(0xFF569CD6)), - onPressed: (_hasText && isConnected) ? _send : null, - tooltip: 'Send', + icon: Icon( + isConnected ? Icons.send : Icons.schedule_send, + color: + isConnected ? const Color(0xFF569CD6) : Colors.orange, + ), + onPressed: _hasText ? _send : null, + tooltip: isConnected ? 'Send' : 'Queue message', ), ), ), diff --git a/apps/mobile/lib/features/chat/presentation/widgets/message_bubble.dart b/apps/mobile/lib/features/chat/presentation/widgets/message_bubble.dart index 832d910..e5a7b15 100644 --- a/apps/mobile/lib/features/chat/presentation/widgets/message_bubble.dart +++ b/apps/mobile/lib/features/chat/presentation/widgets/message_bubble.dart @@ -57,7 +57,10 @@ class MessageBubble extends StatelessWidget { : Column( crossAxisAlignment: CrossAxisAlignment.start, children: msg.parts - .map((p) => MessagePartWidget(part: p)) + .map((p) => MessagePartWidget( + part: p, + metadata: msg.metadata, + )) .toList(), ), ), @@ -93,8 +96,8 @@ class _BubbleLayout extends StatelessWidget { alignment: isUser ? Alignment.centerRight : Alignment.centerLeft, child: Container( margin: const EdgeInsets.symmetric(vertical: 4), - constraints: BoxConstraints( - maxWidth: MediaQuery.of(context).size.width * 0.78), + constraints: + BoxConstraints(maxWidth: MediaQuery.of(context).size.width * 0.78), decoration: BoxDecoration( color: isUser ? const Color(0xFF569CD6) : const Color(0xFF252526), borderRadius: BorderRadius.only( diff --git a/apps/mobile/lib/features/chat/presentation/widgets/message_part_widget.dart b/apps/mobile/lib/features/chat/presentation/widgets/message_part_widget.dart index c594921..672a360 100644 --- a/apps/mobile/lib/features/chat/presentation/widgets/message_part_widget.dart +++ b/apps/mobile/lib/features/chat/presentation/widgets/message_part_widget.dart @@ -6,7 +6,15 @@ import 'tool_card.dart'; class MessagePartWidget extends StatelessWidget { final MessagePart part; - const MessagePartWidget({super.key, required this.part}); + + /// Optional metadata from the parent message (used for approval state). + final Map? metadata; + + const MessagePartWidget({ + super.key, + required this.part, + this.metadata, + }); @override Widget build(BuildContext context) { @@ -24,8 +32,10 @@ class MessagePartWidget extends StatelessWidget { color: const Color(0xFF1E1E1E), borderRadius: BorderRadius.circular(6), ), - h1: const TextStyle(color: Color(0xFF569CD6), fontWeight: FontWeight.bold), - h2: const TextStyle(color: Color(0xFF569CD6), fontWeight: FontWeight.bold), + h1: const TextStyle( + color: Color(0xFF569CD6), fontWeight: FontWeight.bold), + h2: const TextStyle( + color: Color(0xFF569CD6), fontWeight: FontWeight.bold), h3: const TextStyle(color: Color(0xFF569CD6)), blockquote: const TextStyle(color: Color(0xFF9CDCFE)), listBullet: const TextStyle(color: Colors.grey), @@ -36,13 +46,15 @@ class MessagePartWidget extends StatelessWidget { params: params, id: id, isCompleted: false, + metadata: metadata, ), toolResult: (toolCallId, result) => ToolCard( - toolName: toolCallId, + toolName: (result.metadata?['tool'] as String?) ?? toolCallId, params: const {}, id: toolCallId, isCompleted: true, result: result, + metadata: metadata, ), thinking: (content) => _ThinkingBlock(content: content), ); diff --git a/apps/mobile/lib/features/chat/presentation/widgets/tool_card.dart b/apps/mobile/lib/features/chat/presentation/widgets/tool_card.dart index f28c78b..697009d 100644 --- a/apps/mobile/lib/features/chat/presentation/widgets/tool_card.dart +++ b/apps/mobile/lib/features/chat/presentation/widgets/tool_card.dart @@ -2,6 +2,21 @@ import 'package:flutter/material.dart'; import '../../../../core/models/message_models.dart'; +/// Visual state of a tool card in the chat timeline. +enum ToolState { + /// Tool is pending user approval. + pendingApproval, + + /// Tool is executing (running). + running, + + /// Tool completed successfully. + completed, + + /// Tool failed. + failed, +} + class ToolCard extends StatefulWidget { final String toolName; final Map params; @@ -9,6 +24,9 @@ class ToolCard extends StatefulWidget { final bool isCompleted; final ToolResult? result; + /// Optional metadata from parent message (contains approval state like 'risk_level'). + final Map? metadata; + const ToolCard({ super.key, required this.toolName, @@ -16,6 +34,7 @@ class ToolCard extends StatefulWidget { this.id, required this.isCompleted, this.result, + this.metadata, }); @override @@ -29,6 +48,29 @@ class _ToolCardState extends State late AnimationController _expandController; late Animation _expandAnimation; + /// Determines the visual state of this tool card. + ToolState get _state { + final riskLevel = widget.metadata?['risk_level'] as String?; + // If risk_level exists in metadata and tool is not completed, it's pending approval + if (riskLevel != null && !widget.isCompleted) { + return ToolState.pendingApproval; + } + if (!widget.isCompleted) return ToolState.running; + if (widget.result?.success ?? false) return ToolState.completed; + return ToolState.failed; + } + + /// The risk level from metadata (defaults to low if not set). + RiskLevel get _riskLevel { + final level = widget.metadata?['risk_level'] as String?; + return switch (level) { + 'medium' => RiskLevel.medium, + 'high' => RiskLevel.high, + 'critical' => RiskLevel.critical, + _ => RiskLevel.low, + }; + } + @override void initState() { super.initState(); @@ -59,80 +101,183 @@ class _ToolCardState extends State } Color get _statusColor { - if (!widget.isCompleted) return const Color(0xFF569CD6); - return (widget.result?.success ?? false) - ? const Color(0xFF4EC9B0) - : Colors.redAccent; + return switch (_state) { + ToolState.pendingApproval => _riskBadgeColor, + ToolState.running => const Color(0xFF569CD6), + ToolState.completed => const Color(0xFF4EC9B0), + ToolState.failed => Colors.redAccent, + }; + } + + Color get _riskBadgeColor { + return switch (_riskLevel) { + RiskLevel.low => const Color(0xFF4CAF50), + RiskLevel.medium => const Color(0xFFFF9800), + RiskLevel.high => const Color(0xFFF44747), + RiskLevel.critical => const Color(0xFF8B0000), + }; } IconData get _statusIcon { - if (!widget.isCompleted) return Icons.hourglass_empty; - return (widget.result?.success ?? false) ? Icons.check_circle : Icons.error; + return switch (_state) { + ToolState.pendingApproval => Icons.pending_actions, + ToolState.running => Icons.hourglass_empty, + ToolState.completed => Icons.check_circle, + ToolState.failed => Icons.error, + }; } String get _statusLabel { - if (!widget.isCompleted) return 'running'; - return (widget.result?.success ?? false) ? 'succeeded' : 'failed'; + return switch (_state) { + ToolState.pendingApproval => 'approval required', + ToolState.running => 'running', + ToolState.completed => 'succeeded', + ToolState.failed => 'failed', + }; } @override Widget build(BuildContext context) { + final isPendingApproval = _state == ToolState.pendingApproval; + return Semantics( label: 'Tool: ${widget.toolName}, status: $_statusLabel', child: Card( - color: const Color(0xFF2D2D2D), - elevation: 2, - shape: RoundedRectangleBorder(borderRadius: BorderRadius.circular(8)), - margin: const EdgeInsets.symmetric(vertical: 4), - child: Column( - crossAxisAlignment: CrossAxisAlignment.start, - children: [ - // Header - Padding( - padding: const EdgeInsets.all(10), - child: Row( - children: [ - _ToolIcon(toolName: widget.toolName), - const SizedBox(width: 8), - Expanded( - child: Text( - widget.toolName, - style: const TextStyle( + color: const Color(0xFF2D2D2D), + elevation: 2, + shape: RoundedRectangleBorder( + borderRadius: BorderRadius.circular(8), + side: isPendingApproval + ? BorderSide( + color: _riskBadgeColor.withValues(alpha: 0.5), width: 2) + : BorderSide.none, + ), + margin: const EdgeInsets.symmetric(vertical: 4), + child: Column( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + // Header with risk badge for pending approvals + Padding( + padding: const EdgeInsets.all(10), + child: Row( + children: [ + _ToolIcon(toolName: widget.toolName), + const SizedBox(width: 8), + Expanded( + child: Text( + widget.toolName, + style: const TextStyle( color: Colors.white, fontWeight: FontWeight.w600, fontFamily: 'JetBrainsMono', - fontSize: 13), - overflow: TextOverflow.ellipsis, + fontSize: 13, + ), + overflow: TextOverflow.ellipsis, + ), ), - ), - Icon(_statusIcon, color: _statusColor, size: 18), - ], - ), - ), - // Params expandable - if (widget.params.isNotEmpty) - _ExpandableSection( - label: 'Parameters', - expanded: _paramsExpanded, - onTap: () => - setState(() => _paramsExpanded = !_paramsExpanded), - child: _KeyValueList(map: widget.params), + if (isPendingApproval) ...[ + _RiskBadge(level: _riskLevel, color: _riskBadgeColor), + const SizedBox(width: 8), + ], + Icon(_statusIcon, color: _statusColor, size: 18), + ], + ), ), - // Result expandable - if (widget.isCompleted && widget.result != null) - SizeTransition( - sizeFactor: _expandAnimation, - child: _ExpandableSection( - label: 'Result', - expanded: _resultExpanded, - onTap: () => - setState(() => _resultExpanded = !_resultExpanded), - child: _ResultContent(result: widget.result!), + // Approval required banner + if (isPendingApproval) _ApprovalBanner(riskLevel: _riskLevel), + if (widget.params.isNotEmpty) + _ExpandableSection( + label: 'Parameters', + expanded: _paramsExpanded, + onTap: () => setState(() => _paramsExpanded = !_paramsExpanded), + child: _KeyValueList(map: widget.params), + ), + if (widget.isCompleted && widget.result != null) + SizeTransition( + sizeFactor: _expandAnimation, + child: _ExpandableSection( + label: 'Result', + expanded: _resultExpanded, + onTap: () => + setState(() => _resultExpanded = !_resultExpanded), + child: _ResultContent(result: widget.result!), + ), + ), + ], + ), + ), + ); + } +} + +/// Risk level badge shown in pending approval state. +class _RiskBadge extends StatelessWidget { + final RiskLevel level; + final Color color; + + const _RiskBadge({required this.level, required this.color}); + + @override + Widget build(BuildContext context) { + return Container( + padding: const EdgeInsets.symmetric(horizontal: 8, vertical: 3), + decoration: BoxDecoration( + color: color.withValues(alpha: 0.15), + borderRadius: BorderRadius.circular(4), + border: Border.all(color: color.withValues(alpha: 0.4)), + ), + child: Text( + level.name.toUpperCase(), + style: TextStyle( + fontSize: 10, + fontWeight: FontWeight.w700, + color: color, + ), + ), + ); + } +} + +/// Banner shown when approval is required for a tool. +class _ApprovalBanner extends StatelessWidget { + final RiskLevel riskLevel; + + const _ApprovalBanner({required this.riskLevel}); + + @override + Widget build(BuildContext context) { + final color = switch (riskLevel) { + RiskLevel.low => const Color(0xFF4CAF50), + RiskLevel.medium => const Color(0xFFFF9800), + RiskLevel.high => const Color(0xFFF44747), + RiskLevel.critical => const Color(0xFF8B0000), + }; + + return Container( + width: double.infinity, + padding: const EdgeInsets.symmetric(horizontal: 12, vertical: 10), + margin: const EdgeInsets.symmetric(horizontal: 12, vertical: 4), + decoration: BoxDecoration( + color: color.withValues(alpha: 0.1), + borderRadius: BorderRadius.circular(6), + border: Border.all(color: color.withValues(alpha: 0.3)), + ), + child: Row( + children: [ + Icon(Icons.pending_actions, size: 16, color: color), + const SizedBox(width: 8), + Expanded( + child: Text( + 'Approval required — check Approvals tab', + style: TextStyle( + color: color, + fontSize: 12, + fontWeight: FontWeight.w500, ), ), + ), ], ), - ), ); } } @@ -143,10 +288,14 @@ class _ToolIcon extends StatelessWidget { IconData get _icon { final name = toolName.toLowerCase(); - if (name.contains('file') || name.contains('read') || name.contains('write')) { + if (name.contains('file') || + name.contains('read') || + name.contains('write')) { return Icons.description; } - if (name.contains('bash') || name.contains('shell') || name.contains('exec')) { + if (name.contains('bash') || + name.contains('shell') || + name.contains('exec')) { return Icons.terminal; } if (name.contains('search') || name.contains('grep')) { From 30cee7d523de0606d688c8ee02fad5ec349277d2 Mon Sep 17 00:00:00 2001 From: MasuRii Date: Fri, 20 Mar 2026 12:56:34 +0800 Subject: [PATCH 17/22] feat(bridge): enhance agent SDK integration and protocol handling Expand session manager with lifecycle management and recovery. Extend tool executor with comprehensive command handling. Add protocol mapper for hook event transformation. Implement agent runtime abstraction for SDK operations. Enhance websocket message handler with connection management. Update types and configuration for extended protocol support. - Expand agent_sdk_adapter.ts with SDK integration - Enhance session_manager.ts with session lifecycle - Extend tool_executor.ts with command execution - Add agent_runtime.ts for SDK abstraction - Add protocol_mapper.ts for event transformation - Update event_queue.ts, receiver.ts, validator.ts - Enhance message_handler.ts for websocket protocol - Update types.ts with extended type definitions --- packages/bridge/src/agents/agent_runtime.ts | 164 ++++++++ .../bridge/src/agents/agent_sdk_adapter.ts | 72 +++- packages/bridge/src/agents/session_manager.ts | 358 +++++++++++++----- packages/bridge/src/agents/tool_executor.ts | 158 +++++++- packages/bridge/src/config.ts | 4 + packages/bridge/src/git/diff_parser.ts | 63 +-- packages/bridge/src/hooks/event_queue.ts | 56 ++- packages/bridge/src/hooks/protocol_mapper.ts | 172 +++++++++ packages/bridge/src/hooks/receiver.ts | 41 +- packages/bridge/src/hooks/validator.ts | 43 ++- .../bridge/src/notifications/dispatcher.ts | 189 +++++++-- packages/bridge/src/server.ts | 5 +- packages/bridge/src/types.ts | 187 +++++---- .../bridge/src/websocket/message_handler.ts | 261 +++++++++---- 14 files changed, 1380 insertions(+), 393 deletions(-) create mode 100644 packages/bridge/src/agents/agent_runtime.ts create mode 100644 packages/bridge/src/hooks/protocol_mapper.ts diff --git a/packages/bridge/src/agents/agent_runtime.ts b/packages/bridge/src/agents/agent_runtime.ts new file mode 100644 index 0000000..8a76fa6 --- /dev/null +++ b/packages/bridge/src/agents/agent_runtime.ts @@ -0,0 +1,164 @@ +import Anthropic from "@anthropic-ai/sdk"; + +export interface AgentToolDefinition { + name: string; + description: string; + inputSchema: Anthropic.Tool["input_schema"]; +} + +export interface AgentRuntimeTextBlock { + type: "text"; + text: string; +} + +export interface AgentRuntimeToolUseBlock { + type: "tool_use"; + id: string; + name: string; + input: Record; +} + +export interface AgentRuntimeToolResultBlock { + type: "tool_result"; + tool_use_id: string; + content: string; + is_error?: boolean; +} + +export type AgentRuntimeMessageContentBlock = + | AgentRuntimeTextBlock + | AgentRuntimeToolUseBlock + | AgentRuntimeToolResultBlock; + +export interface AgentRuntimeMessage { + role: "user" | "assistant"; + content: string | AgentRuntimeMessageContentBlock[]; +} + +export interface AgentRuntimeTurnRequest { + model: string; + maxTokens: number; + messages: AgentRuntimeMessage[]; + systemPrompt?: string; + tools?: AgentToolDefinition[]; + onTextDelta?: (text: string) => void; +} + +export interface AgentRuntimeTurnResult { + stopReason: string | null; + message: { + role: "assistant"; + content: Array; + }; +} + +export interface AgentRuntime { + runTurn(request: AgentRuntimeTurnRequest): Promise; +} + +function isRecord(value: unknown): value is Record { + return typeof value === "object" && value !== null; +} + +export class AnthropicMessageRuntime implements AgentRuntime { + constructor(private client: Anthropic) {} + + async runTurn(request: AgentRuntimeTurnRequest): Promise { + const streamParams: Anthropic.MessageStreamParams = { + model: request.model, + max_tokens: request.maxTokens, + messages: request.messages.map((message) => this.toAnthropicMessage(message)), + stream: true, + }; + + if (request.systemPrompt) { + (streamParams as Record).system = request.systemPrompt; + } + + if (request.tools && request.tools.length > 0) { + (streamParams as Record).tools = request.tools.map((tool) => ({ + name: tool.name, + description: tool.description, + input_schema: tool.inputSchema, + })); + } + + const stream = this.client.messages.stream(streamParams); + if (request.onTextDelta) { + stream.on("text", (textDelta) => { + request.onTextDelta?.(textDelta); + }); + } + + const finalMessage = await stream.finalMessage(); + + return { + stopReason: finalMessage.stop_reason, + message: { + role: "assistant", + content: finalMessage.content.flatMap((block) => { + const normalized = this.fromAnthropicContentBlock(block); + return normalized ? [normalized] : []; + }), + }, + }; + } + + private toAnthropicMessage(message: AgentRuntimeMessage): Anthropic.MessageParam { + const content = + typeof message.content === "string" + ? message.content + : message.content.map((block) => this.toAnthropicContentBlock(block)); + + return { + role: message.role, + content, + }; + } + + private toAnthropicContentBlock(block: AgentRuntimeMessageContentBlock) { + switch (block.type) { + case "text": + return { + type: "text" as const, + text: block.text, + }; + case "tool_use": + return { + type: "tool_use" as const, + id: block.id, + name: block.name, + input: block.input, + }; + case "tool_result": + return { + type: "tool_result" as const, + tool_use_id: block.tool_use_id, + content: block.content, + is_error: block.is_error, + }; + } + } + + private fromAnthropicContentBlock( + block: Anthropic.ContentBlock, + ): AgentRuntimeTextBlock | AgentRuntimeToolUseBlock | null { + if (block.type === "text") { + return { + type: "text", + text: block.text, + }; + } + + if (block.type === "tool_use") { + return { + type: "tool_use", + id: block.id, + name: block.name, + input: isRecord(block.input) ? block.input : {}, + }; + } + + return null; + } +} diff --git a/packages/bridge/src/agents/agent_sdk_adapter.ts b/packages/bridge/src/agents/agent_sdk_adapter.ts index 7eb9018..f1a76bb 100644 --- a/packages/bridge/src/agents/agent_sdk_adapter.ts +++ b/packages/bridge/src/agents/agent_sdk_adapter.ts @@ -2,13 +2,14 @@ import { v4 as uuidv4 } from "uuid"; import { AgentSessionManager } from "./session_manager"; import type { ConnectionManager } from "../websocket/connection_manager"; import type { - SessionStartPayload, - MessagePayload, ApprovalResponsePayload, - SessionEndPayload, BridgeMessage, - SessionReadyPayload, ErrorPayload, + MessagePayload, + SessionEndPayload, + SessionReadyPayload, + SessionStartPayload, + SupportedAgent, } from "../types"; function log(msg: string): void { @@ -19,6 +20,14 @@ function ts(): string { return new Date().toISOString(); } +function resolveSupportedAgent(agent?: string): SupportedAgent { + if (!agent || agent === "claude-code") { + return "claude-code"; + } + + throw new Error(`Unsupported agent: ${agent}. Only claude-code is currently supported.`); +} + export class AgentSdkAdapter { private sessionManager: AgentSessionManager; private connectionManager: ConnectionManager; @@ -28,27 +37,46 @@ export class AgentSdkAdapter { this.connectionManager = connectionManager; } - async handleSessionStart(payload: SessionStartPayload, clientId: string): Promise { + async handleSessionStart( + payload: SessionStartPayload, + clientId: string, + requestId?: string, + ): Promise { try { - const sessionId = await this.sessionManager.createSession({ - sessionId: payload.session_id, - workingDirectory: payload.working_directory, - systemPrompt: payload.system_prompt, - model: payload.model, - }); + const agent = resolveSupportedAgent(payload.agent); + const shouldResume = payload.resume === true && typeof payload.session_id === "string"; + let sessionId: string; + + if (shouldResume && payload.session_id) { + await this.sessionManager.resumeSession(payload.session_id); + sessionId = payload.session_id; + } else { + sessionId = await this.sessionManager.createSession({ + agent, + sessionId: payload.session_id ?? undefined, + workingDirectory: payload.working_directory, + systemPrompt: payload.system_prompt, + model: payload.model, + }); + } this.connectionManager.addSessionToClient(clientId, sessionId); - const sessions = this.sessionManager.getActiveSessions(); - const session = sessions.find((s) => s.id === sessionId); + const session = this.sessionManager.getSession(sessionId); + if (!session) { + throw new Error(`Session not found after start: ${sessionId}`); + } const readyMsg: BridgeMessage = { type: "session_ready", - id: uuidv4(), + id: requestId ?? uuidv4(), timestamp: ts(), payload: { session_id: sessionId, - model: session?.model ?? "unknown", + agent: session.agent, + working_directory: session.working_directory, + status: "ready", + model: session.model, }, }; this.connectionManager.sendToClient(clientId, readyMsg); @@ -57,12 +85,13 @@ export class AgentSdkAdapter { log(`Failed to start session: ${String(err)}`); const errorMsg: BridgeMessage = { type: "error", - id: uuidv4(), + id: requestId ?? uuidv4(), timestamp: ts(), payload: { - code: "SESSION_START_FAILED", + code: "BRIDGE_ERROR", message: String(err), request_type: "session_start", + recoverable: false, }, }; this.connectionManager.sendToClient(clientId, errorMsg); @@ -79,9 +108,11 @@ export class AgentSdkAdapter { id: uuidv4(), timestamp: ts(), payload: { - code: "MESSAGE_FAILED", + code: "AGENT_ERROR", message: String(err), request_type: "message", + session_id: payload.session_id, + recoverable: true, }, }; this.connectionManager.sendToClient(clientId, errorMsg); @@ -94,6 +125,7 @@ export class AgentSdkAdapter { payload.session_id, payload.tool_call_id, payload.decision, + payload.modifications, ); } catch (err) { log(`Failed to handle approval response: ${String(err)}`); @@ -102,9 +134,11 @@ export class AgentSdkAdapter { id: uuidv4(), timestamp: ts(), payload: { - code: "APPROVAL_FAILED", + code: "TOOL_ERROR", message: String(err), request_type: "approval_response", + session_id: payload.session_id, + recoverable: true, }, }; this.connectionManager.sendToClient(clientId, errorMsg); diff --git a/packages/bridge/src/agents/session_manager.ts b/packages/bridge/src/agents/session_manager.ts index 0dbd510..4e055b0 100644 --- a/packages/bridge/src/agents/session_manager.ts +++ b/packages/bridge/src/agents/session_manager.ts @@ -1,43 +1,143 @@ +import path from "path"; import Anthropic from "@anthropic-ai/sdk"; import { v4 as uuidv4 } from "uuid"; import { config } from "../config"; import { eventBus } from "../notifications/event_bus"; import type { AgentSession, + ApprovalDecision, + ApprovalRequiredPayload, SessionConfig, - StreamStartPayload, StreamChunkPayload, StreamEndPayload, - ApprovalRequiredPayload, - ToolCallPayload, + StreamStartPayload, + SupportedAgent, + ToolExecutionResult, } from "../types"; +import { + AnthropicMessageRuntime, + type AgentRuntime, + type AgentRuntimeMessage, + type AgentRuntimeToolResultBlock, + type AgentRuntimeToolUseBlock, +} from "./agent_runtime"; +import { isWithinAllowedRoot, ToolExecutor } from "./tool_executor"; function log(msg: string): void { console.log(`[${new Date().toISOString()}] [AgentSessionManager] ${msg}`); } +interface PendingToolResolution { + decision: ApprovalDecision; + params: Record; +} + +interface PendingToolCall { + tool: string; + params: Record; + resolve: (resolution: PendingToolResolution) => void; +} + interface InternalSession { meta: AgentSession; - history: Anthropic.MessageParam[]; + history: AgentRuntimeMessage[]; systemPrompt?: string; - pendingToolCalls: Map }>; + pendingToolCalls: Map; +} + +function toSupportedAgent(agent?: SupportedAgent): SupportedAgent { + return agent ?? "claude-code"; +} + +function buildSessionTitle(workingDirectory: string): string { + return path.basename(workingDirectory) || "Claude Code session"; +} + +function mapFinishReason(stopReason: string | null): string { + switch (stopReason) { + case "end_turn": + return "stop"; + case "max_tokens": + return "length"; + case "tool_use": + return "tool_call"; + default: + return stopReason ?? "stop"; + } +} + +function mapRiskLevel(tool: string): ApprovalRequiredPayload["risk_level"] { + switch (tool) { + case "run_command": + case "Bash": + return "high"; + case "edit_file": + case "Edit": + return "medium"; + case "read_file": + case "glob": + case "grep": + case "ls": + case "Read": + case "Glob": + case "Grep": + case "LS": + return "low"; + default: + return "medium"; + } +} + +function formatToolResultForModel(tool: string, result: ToolExecutionResult): string { + const parts = [`Tool: ${tool}`, `Success: ${result.success ? "true" : "false"}`]; + + if (result.content) { + parts.push(`Content:\n${result.content}`); + } + + if (result.diff) { + parts.push(`Diff:\n${result.diff}`); + } + + if (result.error) { + parts.push(`Error:\n${result.error}`); + } + + if (typeof result.duration_ms === "number") { + parts.push(`DurationMs: ${result.duration_ms}`); + } + + return parts.join("\n\n"); } export class AgentSessionManager { - private client: Anthropic; + private runtime: AgentRuntime; + private toolExecutor: ToolExecutor; private sessions = new Map(); - constructor() { - this.client = new Anthropic({ apiKey: config.ANTHROPIC_API_KEY }); + constructor(runtime?: AgentRuntime, toolExecutor?: ToolExecutor) { + this.runtime = + runtime ?? new AnthropicMessageRuntime(new Anthropic({ apiKey: config.ANTHROPIC_API_KEY })); + this.toolExecutor = toolExecutor ?? new ToolExecutor(); } async createSession(sessionConfig: SessionConfig): Promise { const sessionId = sessionConfig.sessionId ?? uuidv4(); + const agent = toSupportedAgent(sessionConfig.agent); + const workingDirectory = path.resolve( + sessionConfig.workingDirectory ?? config.ALLOWED_PROJECT_ROOT, + ); + + if (!isWithinAllowedRoot(workingDirectory)) { + throw new Error(`Working directory is outside of allowed project root: ${workingDirectory}`); + } const meta: AgentSession = { id: sessionId, + agent, + title: buildSessionTitle(workingDirectory), model: sessionConfig.model ?? config.AGENT_MODEL, - working_directory: sessionConfig.workingDirectory ?? config.ALLOWED_PROJECT_ROOT, + working_directory: workingDirectory, created_at: new Date().toISOString(), status: "idle", }; @@ -55,6 +155,7 @@ export class AgentSessionManager { eventBus.emitTyped("session-event", { type: "session_created", session_id: sessionId, + agent: meta.agent, model: meta.model, }); @@ -63,17 +164,24 @@ export class AgentSessionManager { async resumeSession(sessionId: string): Promise { const session = this.sessions.get(sessionId); - if (!session) throw new Error(`Session not found: ${sessionId}`); + if (!session) { + throw new Error(`Session not found: ${sessionId}`); + } + session.meta.status = "idle"; log(`Resumed session: ${sessionId}`); } closeSession(sessionId: string): void { const session = this.sessions.get(sessionId); - if (!session) return; + if (!session) { + return; + } + session.meta.status = "closed"; this.sessions.delete(sessionId); log(`Closed session: ${sessionId}`); + eventBus.emitTyped("session-event", { type: "session_closed", session_id: sessionId, @@ -82,99 +190,86 @@ export class AgentSessionManager { async sendMessage(sessionId: string, content: string, clientId: string): Promise { const session = this.sessions.get(sessionId); - if (!session) throw new Error(`Session not found: ${sessionId}`); + if (!session) { + throw new Error(`Session not found: ${sessionId}`); + } session.meta.status = "active"; session.history.push({ role: "user", content }); const messageId = uuidv4(); - const startPayload: StreamStartPayload = { session_id: sessionId, message_id: messageId, }; + eventBus.emitTyped("session-event", { type: "stream_start", ...startPayload, client_id: clientId, }); - try { - const streamParams: Anthropic.MessageStreamParams = { - model: session.meta.model, - max_tokens: 8192, - messages: session.history, - stream: true, - }; - - if (session.systemPrompt) { - (streamParams as Record)["system"] = session.systemPrompt; - } - - const stream = this.client.messages.stream(streamParams); - - let fullText = ""; - let chunkIndex = 0; - let stopReason = "end_turn"; - - for await (const event of stream) { - if (event.type === "content_block_delta") { - const delta = event.delta; - if (delta.type === "text_delta") { - const chunk = delta.text; - fullText += chunk; + let finishReason = "stop"; + try { + for (let iteration = 0; iteration < config.AGENT_MAX_ITERATIONS; iteration += 1) { + const turn = await this.runtime.runTurn({ + model: session.meta.model, + maxTokens: 8192, + messages: session.history, + systemPrompt: session.systemPrompt, + tools: this.toolExecutor.getToolDefinitions(), + onTextDelta: (textDelta) => { const chunkPayload: StreamChunkPayload = { session_id: sessionId, message_id: messageId, - delta: chunk, - index: chunkIndex++, + content: textDelta, + is_tool_use: false, }; eventBus.emitTyped("stream-chunk", chunkPayload); - } - } else if (event.type === "content_block_start") { - const block = event.content_block; - if (block.type === "tool_use") { - session.pendingToolCalls.set(block.id, { - toolName: block.name, - toolInput: block.input as Record, - }); - - const approvalPayload: ApprovalRequiredPayload = { - session_id: sessionId, - tool_call_id: block.id, - tool_name: block.name, - tool_input: block.input as Record, - message: `Tool call requested: ${block.name}`, - }; - eventBus.emitTyped("tool-event", { - type: "approval_required", - ...approvalPayload, - client_id: clientId, - }); - } - } else if (event.type === "message_delta") { - if (event.delta.stop_reason) { - stopReason = event.delta.stop_reason; - } + }, + }); + + session.history.push({ + role: turn.message.role, + content: turn.message.content, + }); + finishReason = mapFinishReason(turn.stopReason); + + const toolCalls = turn.message.content.filter( + (block): block is AgentRuntimeToolUseBlock => block.type === "tool_use", + ); + + if (turn.stopReason !== "tool_use" || toolCalls.length === 0) { + session.meta.status = "idle"; + const endPayload: StreamEndPayload = { + session_id: sessionId, + message_id: messageId, + finish_reason: finishReason, + }; + + eventBus.emitTyped("session-event", { + type: "stream_end", + ...endPayload, + client_id: clientId, + }); + return; } - } - const finalMsg = await stream.finalMessage(); - session.history.push({ role: "assistant", content: finalMsg.content }); + const toolResults: AgentRuntimeToolResultBlock[] = []; + for (const toolCall of toolCalls) { + toolResults.push(await this.executeApprovedTool(sessionId, clientId, session, toolCall)); + } - session.meta.status = "idle"; + session.history.push({ + role: "user", + content: toolResults, + }); + } - const endPayload: StreamEndPayload = { - session_id: sessionId, - message_id: messageId, - stop_reason: stopReason, - }; - eventBus.emitTyped("session-event", { - type: "stream_end", - ...endPayload, - client_id: clientId, - }); + throw new Error( + `Agent tool loop exceeded configured max iterations: ${config.AGENT_MAX_ITERATIONS}`, + ); } catch (err) { session.meta.status = "idle"; log(`Stream error in session ${sessionId}: ${String(err)}`); @@ -182,40 +277,125 @@ export class AgentSessionManager { } } - async executeToolCall(sessionId: string, toolCallId: string, decision: string): Promise { + async executeToolCall( + sessionId: string, + toolCallId: string, + decision: ApprovalDecision, + modifications: Record | null, + ): Promise { const session = this.sessions.get(sessionId); - if (!session) throw new Error(`Session not found: ${sessionId}`); + if (!session) { + throw new Error(`Session not found: ${sessionId}`); + } const pending = session.pendingToolCalls.get(toolCallId); if (!pending) { - log(`Tool call not found: ${toolCallId}`); - return; + throw new Error(`Tool call not found: ${toolCallId}`); } session.pendingToolCalls.delete(toolCallId); - if (decision === "reject") { + if (decision === "rejected") { log(`Tool call rejected: ${toolCallId}`); eventBus.emitTyped("tool-event", { type: "tool_rejected", session_id: sessionId, tool_call_id: toolCallId, }); + pending.resolve({ decision, params: pending.params }); return; } - log(`Tool call approved: ${toolCallId} (${pending.toolName})`); + const resolvedParams = + decision === "modified" ? (modifications ?? pending.params) : pending.params; + + log(`Tool call ${decision}: ${toolCallId} (${pending.tool})`); eventBus.emitTyped("tool-event", { - type: "tool_approved", + type: decision === "modified" ? "tool_modified" : "tool_approved", session_id: sessionId, tool_call_id: toolCallId, - tool_name: pending.toolName, + tool: pending.tool, + params: resolvedParams, }); + pending.resolve({ decision, params: resolvedParams }); + } + + getSession(sessionId: string): AgentSession | undefined { + return this.sessions.get(sessionId)?.meta; } getActiveSessions(): AgentSession[] { return Array.from(this.sessions.values()) - .filter((s) => s.meta.status !== "closed") - .map((s) => s.meta); + .filter((session) => session.meta.status !== "closed") + .map((session) => session.meta); + } + + private async executeApprovedTool( + sessionId: string, + clientId: string, + session: InternalSession, + toolCall: AgentRuntimeToolUseBlock, + ): Promise { + const approval = await new Promise((resolve) => { + session.pendingToolCalls.set(toolCall.id, { + tool: toolCall.name, + params: toolCall.input, + resolve, + }); + + const approvalPayload: ApprovalRequiredPayload = { + session_id: sessionId, + tool_call_id: toolCall.id, + tool: toolCall.name, + params: toolCall.input, + description: `Approval required for ${toolCall.name}`, + risk_level: mapRiskLevel(toolCall.name), + source: "agent_sdk", + }; + + eventBus.emitTyped("tool-event", { + type: "approval_required", + ...approvalPayload, + client_id: clientId, + }); + }); + + if (approval.decision === "rejected") { + return { + type: "tool_result", + tool_use_id: toolCall.id, + content: `Tool execution rejected by user for ${toolCall.name}.`, + is_error: true, + }; + } + + const execution = await this.toolExecutor.execute( + toolCall.name, + approval.params, + session.meta.working_directory, + ); + + const result: ToolExecutionResult = { + success: execution.success, + content: execution.content, + diff: execution.diff, + error: execution.error, + duration_ms: execution.durationMs, + }; + + eventBus.emitTyped("tool-event", { + type: "tool_result", + session_id: sessionId, + tool_call_id: toolCall.id, + tool: toolCall.name, + result, + }); + + return { + type: "tool_result", + tool_use_id: toolCall.id, + content: formatToolResultForModel(toolCall.name, result), + is_error: !result.success, + }; } } diff --git a/packages/bridge/src/agents/tool_executor.ts b/packages/bridge/src/agents/tool_executor.ts index 9c23d9b..281b79f 100644 --- a/packages/bridge/src/agents/tool_executor.ts +++ b/packages/bridge/src/agents/tool_executor.ts @@ -4,6 +4,7 @@ import { spawn } from "child_process"; import { promisify } from "util"; import { config } from "../config"; import type { ToolResult } from "../types"; +import type { AgentToolDefinition } from "./agent_runtime"; const readFileAsync = promisify(fs.readFile); const writeFileAsync = promisify(fs.writeFile); @@ -16,26 +17,132 @@ function log(msg: string): void { const ALLOWED_COMMANDS = ["git", "flutter", "npm", "node", "dart"]; -function isWithinAllowedRoot(filePath: string): boolean { +function normalizeToolName(tool: string): string { + switch (tool) { + case "Read": + return "read_file"; + case "Edit": + return "edit_file"; + case "Bash": + case "bash_command": + return "run_command"; + case "Glob": + return "glob"; + case "Grep": + return "grep"; + case "LS": + case "list_files": + return "ls"; + default: + return tool; + } +} + +export function isWithinAllowedRoot(filePath: string): boolean { const resolved = path.resolve(filePath); const allowed = path.resolve(config.ALLOWED_PROJECT_ROOT); return resolved.startsWith(allowed + path.sep) || resolved === allowed; } function resolveWithinRoot(filePath: string, workingDir: string): string { - const resolved = path.isAbsolute(filePath) - ? path.resolve(filePath) - : path.resolve(workingDir, filePath); - return resolved; + return path.isAbsolute(filePath) ? path.resolve(filePath) : path.resolve(workingDir, filePath); } export class ToolExecutor { + getToolDefinitions(): AgentToolDefinition[] { + return [ + { + name: "read_file", + description: "Read the UTF-8 contents of a file within the allowed project root.", + inputSchema: { + type: "object", + additionalProperties: false, + properties: { + path: { + type: "string", + description: + "File path to read, absolute or relative to the session working directory.", + }, + }, + required: ["path"], + }, + }, + { + name: "edit_file", + description: "Replace exact text in a file within the allowed project root.", + inputSchema: { + type: "object", + additionalProperties: false, + properties: { + path: { type: "string" }, + old_string: { type: "string" }, + new_string: { type: "string" }, + }, + required: ["path", "old_string", "new_string"], + }, + }, + { + name: "run_command", + description: + "Run an allowlisted command inside the session working directory. Allowed commands: git, flutter, npm, node, dart.", + inputSchema: { + type: "object", + additionalProperties: false, + properties: { + command: { type: "string" }, + description: { type: "string" }, + }, + required: ["command"], + }, + }, + { + name: "glob", + description: "List files matching a glob pattern within the allowed project root.", + inputSchema: { + type: "object", + additionalProperties: false, + properties: { + pattern: { type: "string" }, + base_dir: { type: "string" }, + }, + required: ["pattern"], + }, + }, + { + name: "grep", + description: + "Search file contents for a regular expression within the allowed project root.", + inputSchema: { + type: "object", + additionalProperties: false, + properties: { + pattern: { type: "string" }, + path: { type: "string" }, + }, + required: ["pattern"], + }, + }, + { + name: "ls", + description: "List files and directories within the allowed project root.", + inputSchema: { + type: "object", + additionalProperties: false, + properties: { + path: { type: "string" }, + }, + }, + }, + ]; + } + async execute( tool: string, params: Record, workingDir: string, ): Promise { const start = Date.now(); + const normalizedTool = normalizeToolName(tool); if (!isWithinAllowedRoot(workingDir)) { return { @@ -48,15 +155,15 @@ export class ToolExecutor { try { let result: ToolResult; - switch (tool) { + switch (normalizedTool) { case "read_file": result = await this.readFile(params, workingDir, start); break; case "edit_file": result = await this.editFile(params, workingDir, start); break; - case "bash_command": - result = await this.bashCommand(params, workingDir, start); + case "run_command": + result = await this.runCommand(params, workingDir, start); break; case "glob": result = await this.glob(params, workingDir, start); @@ -64,7 +171,7 @@ export class ToolExecutor { case "grep": result = await this.grep(params, workingDir, start); break; - case "list_files": + case "ls": result = await this.listFiles(params, workingDir, start); break; default: @@ -77,6 +184,7 @@ export class ToolExecutor { } return result; } catch (err) { + log(`Tool ${normalizedTool} failed: ${String(err)}`); return { success: false, content: "", @@ -138,19 +246,37 @@ export class ToolExecutor { const updated = original.replace(oldStr, newStr); await writeFileAsync(resolved, updated, "utf8"); - return { success: true, content: "File updated successfully", durationMs: Date.now() - start }; + return { + success: true, + content: "File updated successfully", + durationMs: Date.now() - start, + diff: `--- ${filePath}\n+++ ${filePath}\n- ${oldStr}\n+ ${newStr}`, + }; } - private bashCommand( + private runCommand( params: Record, workingDir: string, start: number, ): Promise { return new Promise((resolve) => { const command = String(params["command"] ?? ""); - const parts = command.trim().split(/\s+/); + const parts = command + .trim() + .split(/\s+/) + .filter((part) => part.length > 0); const executable = parts[0]; + if (!executable) { + resolve({ + success: false, + content: "", + error: "Command is required", + durationMs: Date.now() - start, + }); + return; + } + if (!ALLOWED_COMMANDS.includes(executable)) { resolve({ success: false, @@ -215,7 +341,6 @@ export class ToolExecutor { }; } - // Use native fs walk for glob const results: string[] = []; await this.walkGlob(baseDir, baseDir, pattern, results); return { success: true, content: results.join("\n"), durationMs: Date.now() - start }; @@ -247,11 +372,8 @@ export class ToolExecutor { if (stat.isDirectory()) { await this.walkGlob(base, full, pattern, results); - } else { - // Simple glob: support * and ** - if (this.matchGlob(rel, pattern)) { - results.push(rel); - } + } else if (this.matchGlob(rel, pattern)) { + results.push(rel); } } } diff --git a/packages/bridge/src/config.ts b/packages/bridge/src/config.ts index 2c04b30..fe4ff77 100644 --- a/packages/bridge/src/config.ts +++ b/packages/bridge/src/config.ts @@ -9,6 +9,10 @@ const configSchema = z.object({ HOOK_TOKEN: z.string().min(1, "HOOK_TOKEN is required"), ANTHROPIC_API_KEY: z.string().min(1, "ANTHROPIC_API_KEY is required"), AGENT_MODEL: z.string().default("claude-opus-4-6"), + AGENT_MAX_ITERATIONS: z + .string() + .default("25") + .transform((v) => parseInt(v, 10)), ALLOWED_PROJECT_ROOT: z.string().min(1, "ALLOWED_PROJECT_ROOT is required"), }); diff --git a/packages/bridge/src/git/diff_parser.ts b/packages/bridge/src/git/diff_parser.ts index 922b24f..09fe638 100644 --- a/packages/bridge/src/git/diff_parser.ts +++ b/packages/bridge/src/git/diff_parser.ts @@ -5,6 +5,23 @@ const OLD_FILE_RE = /^--- (?:a\/(.*)|\/(dev\/null))$/; const NEW_FILE_RE = /^\+\+\+ (?:b\/(.*)|\/(dev\/null))$/; const HUNK_HEADER_RE = /^@@ -(\d+)(?:,(\d+))? \+(\d+)(?:,(\d+))? @@(.*)$/; +function determineFileStatus( + isNew: boolean, + isDeleted: boolean, + isRenamed: boolean, +): DiffFile["status"] { + if (isNew) { + return "added"; + } + if (isDeleted) { + return "deleted"; + } + if (isRenamed) { + return "renamed"; + } + return "modified"; +} + export function parseDiff(rawDiff: string): DiffFile[] { const files: DiffFile[] = []; if (!rawDiff || rawDiff.trim().length === 0) { @@ -33,12 +50,10 @@ export function parseDiff(rawDiff: string): DiffFile[] { let isDeleted = false; let isRenamed = oldPath !== newPath; - // Skip "index ..." lines while (i < lines.length && lines[i].startsWith("index ")) { i++; } - // Parse --- line if (i < lines.length) { const oldMatch = OLD_FILE_RE.exec(lines[i]); if (oldMatch) { @@ -51,7 +66,6 @@ export function parseDiff(rawDiff: string): DiffFile[] { } } - // Parse +++ line if (i < lines.length) { const newMatch = NEW_FILE_RE.exec(lines[i]); if (newMatch) { @@ -65,12 +79,12 @@ export function parseDiff(rawDiff: string): DiffFile[] { } const hunks: DiffHunk[] = []; + let additions = 0; + let deletions = 0; - // Parse hunks while (i < lines.length) { const hunkLine = lines[i]; - // Stop if we hit the next file header if (FILE_HEADER_RE.test(hunkLine)) { break; } @@ -82,9 +96,9 @@ export function parseDiff(rawDiff: string): DiffFile[] { } const oldStart = parseInt(hunkMatch[1], 10); - const oldCount = hunkMatch[2] !== undefined ? parseInt(hunkMatch[2], 10) : 1; + const oldLines = hunkMatch[2] !== undefined ? parseInt(hunkMatch[2], 10) : 1; const newStart = parseInt(hunkMatch[3], 10); - const newCount = hunkMatch[4] !== undefined ? parseInt(hunkMatch[4], 10) : 1; + const newLines = hunkMatch[4] !== undefined ? parseInt(hunkMatch[4], 10) : 1; const header = hunkLine; i++; @@ -93,33 +107,33 @@ export function parseDiff(rawDiff: string): DiffFile[] { let newLineNum = newStart; while (i < lines.length) { - const dl = lines[i]; + const diffLine = lines[i]; - if (FILE_HEADER_RE.test(dl) || HUNK_HEADER_RE.test(dl)) { + if (FILE_HEADER_RE.test(diffLine) || HUNK_HEADER_RE.test(diffLine)) { break; } - if (dl.startsWith("+")) { + if (diffLine.startsWith("+")) { + additions++; diffLines.push({ - type: "addition", - content: dl.slice(1), + type: "added", + content: diffLine.slice(1), new_line_number: newLineNum++, }); - } else if (dl.startsWith("-")) { + } else if (diffLine.startsWith("-")) { + deletions++; diffLines.push({ - type: "deletion", - content: dl.slice(1), + type: "removed", + content: diffLine.slice(1), old_line_number: oldLineNum++, }); - } else if (dl.startsWith(" ") || dl === "") { + } else if (diffLine.startsWith(" ") || diffLine === "") { diffLines.push({ type: "context", - content: dl.startsWith(" ") ? dl.slice(1) : dl, + content: diffLine.startsWith(" ") ? diffLine.slice(1) : diffLine, old_line_number: oldLineNum++, new_line_number: newLineNum++, }); - } else if (dl.startsWith("\\")) { - // "\ No newline at end of file" — skip } i++; @@ -127,20 +141,21 @@ export function parseDiff(rawDiff: string): DiffFile[] { hunks.push({ old_start: oldStart, - old_count: oldCount, + old_lines: oldLines, new_start: newStart, - new_count: newCount, + new_lines: newLines, header, lines: diffLines, }); } files.push({ + path: isDeleted ? oldPath : newPath, old_path: oldPath, new_path: newPath, - is_new: isNew, - is_deleted: isDeleted, - is_renamed: isRenamed, + status: determineFileStatus(isNew, isDeleted, isRenamed), + additions, + deletions, hunks, }); } diff --git a/packages/bridge/src/hooks/event_queue.ts b/packages/bridge/src/hooks/event_queue.ts index eb43030..51174e0 100644 --- a/packages/bridge/src/hooks/event_queue.ts +++ b/packages/bridge/src/hooks/event_queue.ts @@ -1,34 +1,62 @@ -import type { HookEvent } from "../types"; +import type { BridgeMessage } from "../types"; const MAX_QUEUE_SIZE = 1000; +interface QueuedMessage { + message: BridgeMessage; + sessionId?: string; + notificationId?: string; +} + export class EventQueue { - private queue: HookEvent[] = []; + private queue: QueuedMessage[] = []; - enqueue(event: HookEvent): void { + enqueue( + message: BridgeMessage, + options: { sessionId?: string; notificationId?: string } = {}, + ): void { if (this.queue.length >= MAX_QUEUE_SIZE) { - this.queue.shift(); // drop oldest + this.queue.shift(); } - this.queue.push(event); + + this.queue.push({ + message, + sessionId: options.sessionId, + notificationId: options.notificationId, + }); } - dequeue(sessionId?: string): HookEvent[] { + replay(sessionId?: string): BridgeMessage[] { if (!sessionId) { - const all = [...this.queue]; - this.queue = []; - return all; + return this.queue.map((entry) => entry.message); + } + + return this.queue + .filter((entry) => entry.sessionId === sessionId) + .map((entry) => entry.message); + } + + acknowledgeNotifications(notificationIds: string[]): void { + if (notificationIds.length === 0) { + return; } - const matching = this.queue.filter((e) => e.session_id === sessionId); - this.queue = this.queue.filter((e) => e.session_id !== sessionId); - return matching; + + const acknowledged = new Set(notificationIds); + this.queue = this.queue.filter((entry) => { + if (!entry.notificationId) { + return true; + } + return !acknowledged.has(entry.notificationId); + }); } clear(sessionId?: string): void { if (!sessionId) { this.queue = []; - } else { - this.queue = this.queue.filter((e) => e.session_id !== sessionId); + return; } + + this.queue = this.queue.filter((entry) => entry.sessionId !== sessionId); } size(): number { diff --git a/packages/bridge/src/hooks/protocol_mapper.ts b/packages/bridge/src/hooks/protocol_mapper.ts new file mode 100644 index 0000000..c57ecf8 --- /dev/null +++ b/packages/bridge/src/hooks/protocol_mapper.ts @@ -0,0 +1,172 @@ +import { v4 as uuidv4 } from "uuid"; +import type { + BridgeMessage, + ClaudeEventPayload, + ApprovalRequiredPayload, + HookEvent, + NotificationPayload, + RiskLevel, + ToolExecutionResult, + ToolResultPayload, +} from "../types"; + +function timestamp(): string { + return new Date().toISOString(); +} + +function asRecord(value: unknown): Record | null { + return typeof value === "object" && value !== null ? (value as Record) : null; +} + +function asString(value: unknown): string | undefined { + return typeof value === "string" && value.length > 0 ? value : undefined; +} + +function asBoolean(value: unknown): boolean | undefined { + return typeof value === "boolean" ? value : undefined; +} + +function asRiskLevel(value: unknown): RiskLevel { + if (value === "low" || value === "medium" || value === "high" || value === "critical") { + return value; + } + return "medium"; +} + +function extractTool(payload: Record): string { + return asString(payload.tool) ?? asString(payload.tool_name) ?? "unknown_tool"; +} + +function extractToolParams(payload: Record): Record { + return asRecord(payload.params) ?? asRecord(payload.tool_input) ?? {}; +} + +function extractToolCallId(payload: Record): string { + return asString(payload.tool_call_id) ?? uuidv4(); +} + +function createClaudeEventMessage(event: HookEvent): BridgeMessage { + return { + type: "claude_event", + id: uuidv4(), + timestamp: timestamp(), + payload: { + event_type: event.event_type, + session_id: event.session_id, + timestamp: event.timestamp, + payload: event.payload, + }, + }; +} + +function createApprovalRequiredMessage( + event: HookEvent, +): BridgeMessage | null { + if (event.event_type !== "PreToolUse") { + return null; + } + + const payload = event.payload; + const tool = extractTool(payload); + const params = extractToolParams(payload); + const description = + asString(payload.description) ?? asString(payload.message) ?? `Approval required for ${tool}`; + + return { + type: "approval_required", + id: uuidv4(), + timestamp: timestamp(), + payload: { + session_id: event.session_id, + tool_call_id: extractToolCallId(payload), + tool, + params, + description, + risk_level: asRiskLevel(payload.risk_level), + source: "hooks", + }, + }; +} + +function createToolResultMessage(event: HookEvent): BridgeMessage | null { + if (event.event_type !== "PostToolUse") { + return null; + } + + const payload = event.payload; + const resultPayload = asRecord(payload.result); + const result: ToolExecutionResult = { + success: asBoolean(resultPayload?.success) ?? true, + content: + asString(resultPayload?.content) ?? + asString(payload.content) ?? + JSON.stringify(resultPayload ?? payload), + diff: asString(resultPayload?.diff), + error: asString(resultPayload?.error), + duration_ms: + typeof payload.duration_ms === "number" + ? payload.duration_ms + : typeof resultPayload?.duration_ms === "number" + ? resultPayload.duration_ms + : undefined, + }; + + return { + type: "tool_result", + id: uuidv4(), + timestamp: timestamp(), + payload: { + session_id: event.session_id, + tool_call_id: extractToolCallId(payload), + tool: extractTool(payload), + result, + }, + }; +} + +function createNotificationMessage(event: HookEvent): BridgeMessage | null { + if (event.event_type !== "Notification") { + return null; + } + + const payload = event.payload; + const notificationId = uuidv4(); + const level = asString(payload.level); + const priority = level === "error" || level === "warning" ? "high" : "normal"; + + return { + type: "notification", + id: notificationId, + timestamp: timestamp(), + payload: { + notification_id: notificationId, + session_id: event.session_id, + notification_type: asString(payload.notification_type) ?? "agent_idle", + title: asString(payload.title) ?? "Claude Code notification", + body: asString(payload.body) ?? asString(payload.message) ?? JSON.stringify(payload), + priority, + data: asRecord(payload.data) ?? asRecord(payload.metadata) ?? undefined, + }, + }; +} + +export function buildHookProtocolMessages(event: HookEvent): BridgeMessage[] { + const messages: BridgeMessage[] = [createClaudeEventMessage(event)]; + + const approvalRequiredMessage = createApprovalRequiredMessage(event); + if (approvalRequiredMessage) { + messages.push(approvalRequiredMessage); + } + + const toolResultMessage = createToolResultMessage(event); + if (toolResultMessage) { + messages.push(toolResultMessage); + } + + const notificationMessage = createNotificationMessage(event); + if (notificationMessage) { + messages.push(notificationMessage); + } + + return messages; +} diff --git a/packages/bridge/src/hooks/receiver.ts b/packages/bridge/src/hooks/receiver.ts index e4e4766..cf389a2 100644 --- a/packages/bridge/src/hooks/receiver.ts +++ b/packages/bridge/src/hooks/receiver.ts @@ -1,11 +1,10 @@ import { Router } from "express"; -import { v4 as uuidv4 } from "uuid"; import { validateHookToken } from "../auth/token_validator"; import { validateHookEvent } from "./validator"; import { EventQueue } from "./event_queue"; -import { eventBus } from "../notifications/event_bus"; import type { ConnectionManager } from "../websocket/connection_manager"; -import type { BridgeMessage, ClaudeEventPayload, HookEvent } from "../types"; +import type { HookEvent } from "../types"; +import { buildHookProtocolMessages } from "./protocol_mapper"; function log(msg: string): void { console.log(`[${new Date().toISOString()}] [HookReceiver] ${msg}`); @@ -28,25 +27,23 @@ export function createHooksRouter( const event: HookEvent = body; log(`Received event: ${event.event_type} (session=${event.session_id})`); - eventQueue.enqueue(event); - - const claudeEventPayload: ClaudeEventPayload = { - event_type: event.event_type, - session_id: event.session_id, - timestamp: event.timestamp, - payload: event.payload, - }; - - eventBus.emitTyped("claude-event", claudeEventPayload); - - const msg: BridgeMessage = { - type: "claude_event", - id: uuidv4(), - timestamp: new Date().toISOString(), - payload: claudeEventPayload, - }; - - connectionManager.broadcast(msg); + const messages = buildHookProtocolMessages(event); + for (const message of messages) { + const notificationId = + message.type === "notification" && + typeof message.payload === "object" && + message.payload !== null && + "notification_id" in message.payload && + typeof (message.payload as { notification_id?: unknown }).notification_id === "string" + ? ((message.payload as { notification_id: string }).notification_id as string) + : undefined; + + eventQueue.enqueue(message, { + sessionId: event.session_id, + notificationId, + }); + connectionManager.broadcast(message); + } res.status(200).json({ received: true }); }); diff --git a/packages/bridge/src/hooks/validator.ts b/packages/bridge/src/hooks/validator.ts index 2aa849e..92e1b3a 100644 --- a/packages/bridge/src/hooks/validator.ts +++ b/packages/bridge/src/hooks/validator.ts @@ -1,31 +1,62 @@ import type { HookEvent } from "../types"; +const MAX_EVENT_AGE_MS = 5 * 60 * 1000; +const MAX_FUTURE_SKEW_MS = 30 * 1000; + export const VALID_EVENT_TYPES: string[] = [ + "SessionStart", + "SessionEnd", "PreToolUse", "PostToolUse", + "UserPromptSubmit", "Notification", "Stop", "SubagentStop", "PreCompact", ]; +function isRecord(value: unknown): value is Record { + return typeof value === "object" && value !== null; +} + +function isValidTimestamp(value: unknown): value is string { + if (typeof value !== "string" || value.length === 0) { + return false; + } + + const timestamp = Date.parse(value); + if (Number.isNaN(timestamp)) { + return false; + } + + const age = Date.now() - timestamp; + return age <= MAX_EVENT_AGE_MS && age >= -MAX_FUTURE_SKEW_MS; +} + export function validateHookEvent(event: unknown): event is HookEvent { - if (typeof event !== "object" || event === null) { + if (!isRecord(event)) { return false; } - const e = event as Record; - if (typeof e["event_type"] !== "string" || e["event_type"].length === 0) { + if ( + typeof event.event_type !== "string" || + event.event_type.length === 0 || + !VALID_EVENT_TYPES.includes(event.event_type) + ) { return false; } - if (typeof e["session_id"] !== "string" || e["session_id"].length === 0) { + + if (typeof event.session_id !== "string" || event.session_id.length === 0) { return false; } - if (typeof e["timestamp"] !== "string" || e["timestamp"].length === 0) { + + if (!isValidTimestamp(event.timestamp)) { return false; } - if (typeof e["payload"] !== "object" || e["payload"] === null) { + + if (!isRecord(event.payload)) { return false; } + return true; } diff --git a/packages/bridge/src/notifications/dispatcher.ts b/packages/bridge/src/notifications/dispatcher.ts index 0a1674f..0222267 100644 --- a/packages/bridge/src/notifications/dispatcher.ts +++ b/packages/bridge/src/notifications/dispatcher.ts @@ -1,44 +1,168 @@ import { v4 as uuidv4 } from "uuid"; import { eventBus } from "./event_bus"; +import type { EventQueue } from "../hooks/event_queue"; import type { ConnectionManager } from "../websocket/connection_manager"; -import type { BridgeMessage, ClaudeEventPayload, StreamChunkPayload } from "../types"; +import type { + ApprovalRequiredPayload, + BridgeMessage, + StreamChunkPayload, + StreamEndPayload, + StreamStartPayload, + ToolResultPayload, +} from "../types"; function timestamp(): string { return new Date().toISOString(); } +function isRecord(value: unknown): value is Record { + return typeof value === "object" && value !== null; +} + +function asString(value: unknown): string | undefined { + return typeof value === "string" ? value : undefined; +} + export class Dispatcher { private connectionManager: ConnectionManager; + private eventQueue?: EventQueue; - constructor(connectionManager: ConnectionManager) { + constructor(connectionManager: ConnectionManager, eventQueue?: EventQueue) { this.connectionManager = connectionManager; + this.eventQueue = eventQueue; this.subscribe(); } private subscribe(): void { - eventBus.onTyped("claude-event", (payload) => { - const msg: BridgeMessage = { - type: "claude_event", - id: uuidv4(), - timestamp: timestamp(), - payload: payload as ClaudeEventPayload, - }; - const sessionId = (payload as ClaudeEventPayload).session_id; - this.broadcast(msg, sessionId); + eventBus.onTyped("session-event", (payload) => { + if (!isRecord(payload) || typeof payload.type !== "string") { + return; + } + + switch (payload.type) { + case "stream_start": + this.broadcastToSession(payload.session_id, { + type: "stream_start", + id: uuidv4(), + timestamp: timestamp(), + payload: { + session_id: asString(payload.session_id) ?? "", + message_id: asString(payload.message_id) ?? "", + } satisfies StreamStartPayload, + }); + break; + + case "stream_end": + this.broadcastToSession(payload.session_id, { + type: "stream_end", + id: uuidv4(), + timestamp: timestamp(), + payload: { + session_id: asString(payload.session_id) ?? "", + message_id: asString(payload.message_id) ?? "", + finish_reason: asString(payload.finish_reason) ?? "stop", + } satisfies StreamEndPayload, + }); + break; + + case "session_closed": + this.broadcastToSession(payload.session_id, { + type: "session_end", + id: uuidv4(), + timestamp: timestamp(), + payload: { + session_id: asString(payload.session_id) ?? "", + reason: "completed", + }, + }); + break; + + default: + break; + } + }); + + eventBus.onTyped("tool-event", (payload) => { + if (!isRecord(payload) || typeof payload.type !== "string") { + return; + } + + if (payload.type === "approval_required") { + this.broadcastToSession(payload.session_id, { + type: "approval_required", + id: uuidv4(), + timestamp: timestamp(), + payload: { + session_id: asString(payload.session_id) ?? "", + tool_call_id: asString(payload.tool_call_id) ?? "", + tool: asString(payload.tool) ?? "unknown_tool", + params: isRecord(payload.params) ? payload.params : {}, + description: asString(payload.description) ?? "Approval required", + risk_level: + payload.risk_level === "low" || + payload.risk_level === "medium" || + payload.risk_level === "high" || + payload.risk_level === "critical" + ? payload.risk_level + : "medium", + source: payload.source === "hooks" ? "hooks" : "agent_sdk", + } satisfies ApprovalRequiredPayload, + }); + return; + } + + if (payload.type === "tool_result") { + const message: BridgeMessage = { + type: "tool_result", + id: uuidv4(), + timestamp: timestamp(), + payload: { + session_id: asString(payload.session_id) ?? "", + tool_call_id: asString(payload.tool_call_id) ?? "", + tool: asString(payload.tool) ?? "unknown_tool", + result: isRecord(payload.result) + ? { + success: payload.result.success === true, + content: asString(payload.result.content) ?? "", + diff: asString(payload.result.diff), + error: asString(payload.result.error), + duration_ms: + typeof payload.result.duration_ms === "number" + ? payload.result.duration_ms + : undefined, + } + : { + success: false, + content: "", + error: "Missing tool result payload", + }, + } satisfies ToolResultPayload, + }; + + this.broadcastToSession(payload.session_id, message, { queueForReplay: true }); + } }); eventBus.onTyped("stream-chunk", (payload) => { - const chunk = payload as StreamChunkPayload; + if (!isRecord(payload)) { + return; + } + + const chunkPayload: StreamChunkPayload = { + session_id: asString(payload.session_id) ?? "", + message_id: asString(payload.message_id) ?? "", + content: asString(payload.content) ?? "", + is_tool_use: false, + }; + const msg: BridgeMessage = { type: "stream_chunk", id: uuidv4(), timestamp: timestamp(), - payload: chunk, + payload: chunkPayload, }; - const clients = this.connectionManager.getClientsForSession(chunk.session_id); - for (const client of clients) { - this.connectionManager.sendToClient(client.id, msg); - } + + this.broadcastToSession(chunkPayload.session_id, msg); }); } @@ -48,12 +172,31 @@ export class Dispatcher { broadcast(message: BridgeMessage, sessionId?: string): void { if (sessionId) { - const clients = this.connectionManager.getClientsForSession(sessionId); - for (const client of clients) { - this.connectionManager.sendToClient(client.id, message); - } - } else { - this.connectionManager.broadcast(message); + this.broadcastToSession(sessionId, message); + return; + } + + this.connectionManager.broadcast(message); + } + + private broadcastToSession( + sessionId: unknown, + message: BridgeMessage, + options: { + queueForReplay?: boolean; + } = {}, + ): void { + if (typeof sessionId !== "string" || sessionId.length === 0) { + return; + } + + if (options.queueForReplay) { + this.eventQueue?.enqueue(message, { sessionId }); + } + + const clients = this.connectionManager.getClientsForSession(sessionId); + for (const client of clients) { + this.connectionManager.sendToClient(client.id, message); } } } diff --git a/packages/bridge/src/server.ts b/packages/bridge/src/server.ts index 12e5903..47dc9a0 100644 --- a/packages/bridge/src/server.ts +++ b/packages/bridge/src/server.ts @@ -25,14 +25,15 @@ export async function startServer(): Promise { const gitService = new GitService(config.ALLOWED_PROJECT_ROOT); const eventQueue = new EventQueue(); - // Dispatcher subscribes to event bus and forwards to clients - const _dispatcher = new Dispatcher(connectionManager); + // Dispatcher subscribes to event bus, queues replayable events, and forwards to clients + const _dispatcher = new Dispatcher(connectionManager, eventQueue); const messageHandler = new MessageHandler( connectionManager, agentSdkAdapter, agentSessionManager, gitService, + eventQueue, ); // Express app diff --git a/packages/bridge/src/types.ts b/packages/bridge/src/types.ts index 253f201..ea98cac 100644 --- a/packages/bridge/src/types.ts +++ b/packages/bridge/src/types.ts @@ -1,8 +1,11 @@ import type WebSocket from "ws"; -// --------------------------------------------------------------------------- -// Base envelope -// --------------------------------------------------------------------------- +export const SUPPORTED_AGENTS = ["claude-code"] as const; + +export type SupportedAgent = (typeof SUPPORTED_AGENTS)[number]; +export type AgentSessionStatus = "active" | "idle" | "closed"; +export type RiskLevel = "low" | "medium" | "high" | "critical"; +export type ApprovalDecision = "approved" | "rejected" | "modified"; export interface BridgeMessage { type: string; @@ -11,17 +14,24 @@ export interface BridgeMessage { payload: T; } -// --------------------------------------------------------------------------- -// Auth / connection -// --------------------------------------------------------------------------- - export interface AuthPayload { token: string; + client_version?: string; + platform?: string; +} + +export interface ActiveSessionPayload { + session_id: string; + agent: SupportedAgent; + title: string; + working_directory: string; + status: AgentSessionStatus; } export interface ConnectionAckPayload { - client_id: string; - active_sessions: AgentSession[]; + server_version: string; + supported_agents: SupportedAgent[]; + active_sessions: ActiveSessionPayload[]; } export interface ConnectionErrorPayload { @@ -29,37 +39,32 @@ export interface ConnectionErrorPayload { message: string; } -// --------------------------------------------------------------------------- -// Heartbeat -// --------------------------------------------------------------------------- - export type HeartbeatPingPayload = Record; export type HeartbeatPongPayload = Record; -// --------------------------------------------------------------------------- -// Sessions -// --------------------------------------------------------------------------- - export interface SessionStartPayload { - session_id?: string; + agent?: string; + session_id?: string | null; working_directory?: string; + resume?: boolean; system_prompt?: string; model?: string; } export interface SessionReadyPayload { session_id: string; + agent: SupportedAgent; + working_directory: string; + status: "ready"; model: string; + branch?: string; } export interface SessionEndPayload { session_id: string; + reason?: "user_request" | "timeout" | "error" | "completed"; } -// --------------------------------------------------------------------------- -// Chat / streaming -// --------------------------------------------------------------------------- - export interface MessagePayload { session_id: string; content: string; @@ -74,55 +79,55 @@ export interface StreamStartPayload { export interface StreamChunkPayload { session_id: string; message_id: string; - delta: string; - index: number; + content: string; + is_tool_use: boolean; } export interface StreamEndPayload { session_id: string; message_id: string; - stop_reason: string; + finish_reason: string; } -// --------------------------------------------------------------------------- -// Tools -// --------------------------------------------------------------------------- - export interface ToolCallPayload { session_id: string; tool_call_id: string; - tool_name: string; - tool_input: Record; + tool: string; + params: Record; + description: string; } export interface ApprovalRequiredPayload { session_id: string; tool_call_id: string; - tool_name: string; - tool_input: Record; - message: string; + tool: string; + params: Record; + description: string; + risk_level: RiskLevel; + source: "hooks" | "agent_sdk"; } export interface ApprovalResponsePayload { session_id: string; tool_call_id: string; - decision: "approve" | "reject"; - reason?: string; + decision: ApprovalDecision; + modifications: Record | null; } -export interface ToolResultPayload { - session_id: string; - tool_call_id: string; - tool_name: string; +export interface ToolExecutionResult { success: boolean; content: string; + diff?: string; error?: string; - duration_ms: number; + duration_ms?: number; } -// --------------------------------------------------------------------------- -// Claude hook events -// --------------------------------------------------------------------------- +export interface ToolResultPayload { + session_id: string; + tool_call_id: string; + tool: string; + result: ToolExecutionResult; +} export interface ClaudeEventPayload { event_type: string; @@ -131,10 +136,6 @@ export interface ClaudeEventPayload { payload: Record; } -// --------------------------------------------------------------------------- -// Git -// --------------------------------------------------------------------------- - export interface GitFileChange { path: string; status: "added" | "modified" | "deleted" | "renamed" | "copied" | "untracked" | "unknown"; @@ -142,7 +143,7 @@ export interface GitFileChange { } export interface DiffLine { - type: "context" | "addition" | "deletion"; + type: "context" | "added" | "removed"; content: string; old_line_number?: number; new_line_number?: number; @@ -150,23 +151,29 @@ export interface DiffLine { export interface DiffHunk { old_start: number; - old_count: number; + old_lines: number; new_start: number; - new_count: number; + new_lines: number; header: string; lines: DiffLine[]; } export interface DiffFile { + path: string; old_path: string; new_path: string; - is_new: boolean; - is_deleted: boolean; - is_renamed: boolean; + status: "added" | "modified" | "deleted" | "renamed"; + additions: number; + deletions: number; hunks: DiffHunk[]; } +export interface GitStatusRequestPayload { + session_id?: string; +} + export interface GitStatusPayload { + session_id?: string; branch: string; ahead: number; behind: number; @@ -174,21 +181,21 @@ export interface GitStatusPayload { changes: GitFileChange[]; } -export interface GitStatusResponsePayload extends GitStatusPayload { - request_id?: string; -} +export interface GitStatusResponsePayload extends GitStatusPayload {} export interface GitDiffPayload { + session_id?: string; files?: string[]; cached?: boolean; } export interface GitDiffResponsePayload { + session_id?: string; files: DiffFile[]; - request_id?: string; } export interface GitCommitPayload { + session_id?: string; message: string; files?: string[]; } @@ -199,85 +206,73 @@ export interface GitBranch { is_remote: boolean; } -// --------------------------------------------------------------------------- -// Files -// --------------------------------------------------------------------------- - export interface FileListPayload { + session_id?: string; path: string; offset?: number; limit?: number; includeHidden?: boolean; - request_id?: string; } export interface FileEntry { name: string; - path: string; + path?: string; type: "file" | "directory"; size?: number; modified?: string; } export interface FileListResponsePayload { + session_id?: string; path: string; entries: FileEntry[]; - total: number; - offset: number; - limit: number; - hasMore: boolean; - request_id?: string; + total?: number; + offset?: number; + limit?: number; + hasMore?: boolean; } export interface FileReadPayload { + session_id?: string; path: string; offset?: number; limit?: number; - request_id?: string; } export interface FileReadResponsePayload { + session_id?: string; path: string; content: string; - encoding: "utf8"; - totalLines: number; - offset: number; - limit: number; - hasMore: boolean; - request_id?: string; + size: number; + lines: number; + offset?: number; + limit?: number; + hasMore?: boolean; + encoding?: "utf8"; } -// --------------------------------------------------------------------------- -// Notifications -// --------------------------------------------------------------------------- - export interface NotificationPayload { - notification_id: string; + notification_id?: string; + session_id?: string; + notification_type: string; title: string; body: string; - level: "info" | "warning" | "error"; - session_id?: string; - metadata?: Record; + priority: "low" | "normal" | "high"; + data?: Record; } export interface NotificationAckPayload { - notification_id: string; + notification_ids: string[]; } -// --------------------------------------------------------------------------- -// Error -// --------------------------------------------------------------------------- - export interface ErrorPayload { code: string; message: string; + session_id?: string; + recoverable?: boolean; request_type?: string; } -// --------------------------------------------------------------------------- -// Internal domain models -// --------------------------------------------------------------------------- - export interface MobileClient { id: string; ws: WebSocket; @@ -287,13 +282,16 @@ export interface MobileClient { export interface AgentSession { id: string; + agent: SupportedAgent; + title: string; model: string; working_directory: string; created_at: string; - status: "active" | "idle" | "closed"; + status: AgentSessionStatus; } export interface SessionConfig { + agent?: SupportedAgent; sessionId?: string; workingDirectory?: string; systemPrompt?: string; @@ -310,6 +308,7 @@ export interface HookEvent { export interface ToolResult { success: boolean; content: string; + diff?: string; error?: string; durationMs: number; } diff --git a/packages/bridge/src/websocket/message_handler.ts b/packages/bridge/src/websocket/message_handler.ts index 10b05b5..80e3281 100644 --- a/packages/bridge/src/websocket/message_handler.ts +++ b/packages/bridge/src/websocket/message_handler.ts @@ -4,26 +4,35 @@ import { config } from "../config"; import type { ConnectionManager } from "./connection_manager"; import type { AgentSdkAdapter } from "../agents/agent_sdk_adapter"; import type { GitService } from "../git/git_service"; +import { SUPPORTED_AGENTS } from "../types"; import type { - BridgeMessage, + ActiveSessionPayload, + ApprovalResponsePayload, AuthPayload, + BridgeMessage, ConnectionAckPayload, ConnectionErrorPayload, - SessionStartPayload, - MessagePayload, - ApprovalResponsePayload, - SessionEndPayload, - GitDiffPayload, - GitCommitPayload, - FileListPayload, - FileReadPayload, ErrorPayload, - HeartbeatPongPayload, + FileListPayload, FileListResponsePayload, + FileReadPayload, FileReadResponsePayload, + GitCommitPayload, + GitDiffPayload, + GitDiffResponsePayload, + GitStatusPayload, + GitStatusRequestPayload, + HeartbeatPongPayload, + MessagePayload, + NotificationAckPayload, + SessionEndPayload, + SessionStartPayload, } from "../types"; import type { AgentSessionManager } from "../agents/session_manager"; import { FileService } from "../files/file_service"; +import type { EventQueue } from "../hooks/event_queue"; + +const SERVER_VERSION = "0.1.0"; function log(msg: string): void { console.log(`[${new Date().toISOString()}] [MessageHandler] ${msg}`); @@ -37,12 +46,35 @@ function errorMsg( code: string, message: string, requestType?: string, + sessionId?: string, ): BridgeMessage { return { type: "error", id: uuidv4(), timestamp: ts(), - payload: { code, message, request_type: requestType }, + payload: { + code, + message, + request_type: requestType, + session_id: sessionId, + recoverable: code !== "AUTH_FAILED", + }, + }; +} + +function mapActiveSession(session: { + id: string; + agent: "claude-code"; + title: string; + working_directory: string; + status: "active" | "idle" | "closed"; +}): ActiveSessionPayload { + return { + session_id: session.id, + agent: session.agent, + title: session.title, + working_directory: session.working_directory, + status: session.status, }; } @@ -54,6 +86,7 @@ export class MessageHandler { private agentSdkAdapter: AgentSdkAdapter, private agentSessionManager: AgentSessionManager, private gitService: GitService, + private eventQueue: EventQueue, ) { this.fileService = new FileService(config.ALLOWED_PROJECT_ROOT); } @@ -66,34 +99,31 @@ export class MessageHandler { } catch { this.connectionManager.sendToClient( clientId, - errorMsg("PARSE_ERROR", "Invalid JSON message"), + errorMsg("BRIDGE_ERROR", "Invalid JSON message"), ); return; } - const { type, payload } = msg; + const { type, payload, id } = msg; - // Auth is allowed without authentication if (type === "auth") { - await this.handleAuth(clientId, payload as AuthPayload); + await this.handleAuth(clientId, payload as AuthPayload, id); return; } - // Heartbeat is allowed without authentication (but only if already authenticated in practice) if (type === "heartbeat_ping") { - this.handleHeartbeat(clientId); + this.handleHeartbeat(clientId, id); return; } - // All other messages require authentication const client = this.connectionManager.getClient(clientId); if (!client || !client.authenticated) { this.connectionManager.sendToClient(clientId, { type: "connection_error", - id: uuidv4(), + id: id ?? uuidv4(), timestamp: ts(), payload: { - code: "NOT_AUTHENTICATED", + code: "AUTH_FAILED", message: "Client must authenticate before sending messages", } as ConnectionErrorPayload, }); @@ -103,7 +133,11 @@ export class MessageHandler { try { switch (type) { case "session_start": - await this.agentSdkAdapter.handleSessionStart(payload as SessionStartPayload, clientId); + await this.agentSdkAdapter.handleSessionStart( + payload as SessionStartPayload, + clientId, + id, + ); break; case "message": @@ -122,51 +156,66 @@ export class MessageHandler { break; case "git_status_request": - await this.handleGitStatusRequest(clientId, msg.id); + await this.handleGitStatusRequest( + clientId, + (payload as GitStatusRequestPayload | undefined)?.session_id, + id, + ); break; case "git_commit": - await this.handleGitCommit(clientId, payload as GitCommitPayload); + await this.handleGitCommit(clientId, payload as GitCommitPayload, id); break; case "git_diff": - await this.handleGitDiff(clientId, payload as GitDiffPayload, msg.id); + await this.handleGitDiff(clientId, payload as GitDiffPayload, id); break; case "file_list": - await this.handleFileList(clientId, payload as FileListPayload); + await this.handleFileList(clientId, payload as FileListPayload, id); break; case "file_read": - await this.handleFileRead(clientId, payload as FileReadPayload); + await this.handleFileRead(clientId, payload as FileReadPayload, id); break; case "notification_ack": - // no-op in this implementation + this.handleNotificationAck(payload as NotificationAckPayload); break; default: log(`Unknown message type: ${type} from client ${clientId}`); this.connectionManager.sendToClient( clientId, - errorMsg("UNKNOWN_TYPE", `Unknown message type: ${type}`, type), + errorMsg("BRIDGE_ERROR", `Unknown message type: ${type}`, type), ); } } catch (err) { + const sessionId = + typeof payload === "object" && payload !== null && "session_id" in payload + ? String((payload as { session_id?: unknown }).session_id ?? "") + : undefined; log(`Error handling ${type} for client ${clientId}: ${String(err)}`); - this.connectionManager.sendToClient(clientId, errorMsg("HANDLER_ERROR", String(err), type)); + this.connectionManager.sendToClient( + clientId, + errorMsg("BRIDGE_ERROR", String(err), type, sessionId), + ); } } - private async handleAuth(clientId: string, payload: AuthPayload): Promise { + private async handleAuth( + clientId: string, + payload: AuthPayload, + requestId?: string, + ): Promise { if (!payload?.token || payload.token !== config.BRIDGE_TOKEN) { this.connectionManager.sendToClient(clientId, { type: "connection_error", - id: uuidv4(), + id: requestId ?? uuidv4(), timestamp: ts(), payload: { - code: "INVALID_TOKEN", - message: "Authentication failed: invalid token", + code: "AUTH_FAILED", + message: "Invalid or expired token", } as ConnectionErrorPayload, }); log(`Auth failed for client ${clientId}`); @@ -175,48 +224,81 @@ export class MessageHandler { this.connectionManager.authenticateClient(clientId); - const activeSessions = this.agentSessionManager.getActiveSessions(); + const activeSessions = this.agentSessionManager.getActiveSessions().map(mapActiveSession); const ackMsg: BridgeMessage = { type: "connection_ack", - id: uuidv4(), + id: requestId ?? uuidv4(), timestamp: ts(), payload: { - client_id: clientId, + server_version: SERVER_VERSION, + supported_agents: [...SUPPORTED_AGENTS], active_sessions: activeSessions, }, }; this.connectionManager.sendToClient(clientId, ackMsg); + + for (const queuedMessage of this.eventQueue.replay()) { + this.connectionManager.sendToClient(clientId, queuedMessage); + } + log(`Auth succeeded for client ${clientId}`); } - private handleHeartbeat(clientId: string): void { + private handleHeartbeat(clientId: string, requestId?: string): void { const pong: BridgeMessage = { type: "heartbeat_pong", - id: uuidv4(), + id: requestId ?? uuidv4(), timestamp: ts(), payload: {}, }; this.connectionManager.sendToClient(clientId, pong); } - private async handleGitStatusRequest(clientId: string, requestId?: string): Promise { + private handleNotificationAck(payload: NotificationAckPayload): void { + if (!Array.isArray(payload.notification_ids)) { + return; + } + + this.eventQueue.acknowledgeNotifications( + payload.notification_ids.filter((value): value is string => typeof value === "string"), + ); + } + + private async handleGitStatusRequest( + clientId: string, + sessionId: string | undefined, + requestId?: string, + ): Promise { const status = await this.gitService.getStatus(); + const responsePayload: GitStatusPayload = { + ...status, + session_id: sessionId, + }; + this.connectionManager.sendToClient(clientId, { type: "git_status_response", - id: uuidv4(), + id: requestId ?? uuidv4(), timestamp: ts(), - payload: { ...status, request_id: requestId }, + payload: responsePayload, }); } - private async handleGitCommit(clientId: string, payload: GitCommitPayload): Promise { + private async handleGitCommit( + clientId: string, + payload: GitCommitPayload, + requestId?: string, + ): Promise { await this.gitService.commit(payload.message, payload.files); + this.connectionManager.sendToClient(clientId, { type: "git_status_response", - id: uuidv4(), + id: requestId ?? uuidv4(), timestamp: ts(), - payload: { ...(await this.gitService.getStatus()) }, + payload: { + ...(await this.gitService.getStatus()), + session_id: payload.session_id, + } satisfies GitStatusPayload, }); } @@ -226,15 +308,24 @@ export class MessageHandler { requestId?: string, ): Promise { const files = await this.gitService.getDiff(payload.files, payload.cached); + const responsePayload: GitDiffResponsePayload = { + session_id: payload.session_id, + files, + }; + this.connectionManager.sendToClient(clientId, { type: "git_diff_response", - id: uuidv4(), + id: requestId ?? uuidv4(), timestamp: ts(), - payload: { files, request_id: requestId }, + payload: responsePayload, }); } - private async handleFileList(clientId: string, payload: FileListPayload): Promise { + private async handleFileList( + clientId: string, + payload: FileListPayload, + requestId?: string, + ): Promise { const dirPath = path.resolve(payload.path); const result = await this.fileService.listDirectory(dirPath, { offset: payload.offset, @@ -242,54 +333,60 @@ export class MessageHandler { includeHidden: payload.includeHidden, }); - // Map FileService entries to the wire FileEntry shape (includes path) - const entries = result.entries.map((e) => ({ - name: e.name, - path: path.join(dirPath, e.name), - type: e.type, - size: e.size, - modified: e.modifiedAt, + const entries = result.entries.map((entry) => ({ + name: entry.name, + path: path.join(dirPath, entry.name), + type: entry.type, + size: entry.size, + modified: entry.modifiedAt, })); - const resp: BridgeMessage = { + const responsePayload: FileListResponsePayload = { + session_id: payload.session_id, + path: dirPath, + entries, + total: result.total, + offset: result.offset, + limit: result.limit, + hasMore: result.hasMore, + }; + + this.connectionManager.sendToClient(clientId, { type: "file_list_response", - id: uuidv4(), + id: requestId ?? uuidv4(), timestamp: ts(), - payload: { - path: dirPath, - entries, - total: result.total, - offset: result.offset, - limit: result.limit, - hasMore: result.hasMore, - request_id: payload.request_id, - }, - }; - this.connectionManager.sendToClient(clientId, resp); + payload: responsePayload, + }); } - private async handleFileRead(clientId: string, payload: FileReadPayload): Promise { + private async handleFileRead( + clientId: string, + payload: FileReadPayload, + requestId?: string, + ): Promise { const filePath = path.resolve(payload.path); const result = await this.fileService.readFile(filePath, { offset: payload.offset, limit: payload.limit, }); - const resp: BridgeMessage = { + const responsePayload: FileReadResponsePayload = { + session_id: payload.session_id, + path: filePath, + content: result.content, + size: Buffer.byteLength(result.content, "utf8"), + lines: result.totalLines, + offset: result.offset, + limit: result.limit, + hasMore: result.hasMore, + encoding: "utf8", + }; + + this.connectionManager.sendToClient(clientId, { type: "file_read_response", - id: uuidv4(), + id: requestId ?? uuidv4(), timestamp: ts(), - payload: { - path: filePath, - content: result.content, - encoding: "utf8", - totalLines: result.totalLines, - offset: result.offset, - limit: result.limit, - hasMore: result.hasMore, - request_id: payload.request_id, - }, - }; - this.connectionManager.sendToClient(clientId, resp); + payload: responsePayload, + }); } } From cc4a09e246d52b54e78d32aa5f1c006992f4342d Mon Sep 17 00:00:00 2001 From: MasuRii Date: Fri, 20 Mar 2026 12:56:58 +0800 Subject: [PATCH 18/22] test(bridge): add jest testing infrastructure and unit tests Configure jest for TypeScript testing with mock implementations. Add comprehensive unit tests for all bridge modules including agents, hooks, notifications, and websocket handlers. - Add jest.config.cjs with TypeScript transformation - Add jest.setup.ts with mock configurations - Add tests/agents/* for session and executor tests - Add tests/hooks/* for event queue and validator tests - Add tests/notifications/* for dispatcher tests - Add tests/websocket/* for message handler tests --- packages/bridge/jest.config.cjs | 7 + packages/bridge/package-lock.json | 286 ++++++++++++++++ packages/bridge/package.json | 2 + .../tests/agents/agent_sdk_adapter.test.ts | 223 ++++++++++++ .../tests/agents/session_manager.test.ts | 324 ++++++++++++++++++ .../bridge/tests/agents/tool_executor.test.ts | 53 +++ .../bridge/tests/hooks/event_queue.test.ts | 49 +++ .../tests/hooks/protocol_mapper.test.ts | 94 +++++ packages/bridge/tests/hooks/receiver.test.ts | 250 ++++++++++++++ packages/bridge/tests/hooks/validator.test.ts | 28 ++ packages/bridge/tests/jest.setup.ts | 5 + .../tests/notifications/dispatcher.test.ts | 113 ++++++ .../websocket/connection_manager.test.ts | 287 ++++++++++++++++ .../tests/websocket/message_handler.test.ts | 255 ++++++++++++++ 14 files changed, 1976 insertions(+) create mode 100644 packages/bridge/jest.config.cjs create mode 100644 packages/bridge/tests/agents/agent_sdk_adapter.test.ts create mode 100644 packages/bridge/tests/agents/session_manager.test.ts create mode 100644 packages/bridge/tests/agents/tool_executor.test.ts create mode 100644 packages/bridge/tests/hooks/event_queue.test.ts create mode 100644 packages/bridge/tests/hooks/protocol_mapper.test.ts create mode 100644 packages/bridge/tests/hooks/receiver.test.ts create mode 100644 packages/bridge/tests/hooks/validator.test.ts create mode 100644 packages/bridge/tests/jest.setup.ts create mode 100644 packages/bridge/tests/notifications/dispatcher.test.ts create mode 100644 packages/bridge/tests/websocket/connection_manager.test.ts create mode 100644 packages/bridge/tests/websocket/message_handler.test.ts diff --git a/packages/bridge/jest.config.cjs b/packages/bridge/jest.config.cjs new file mode 100644 index 0000000..b47f49b --- /dev/null +++ b/packages/bridge/jest.config.cjs @@ -0,0 +1,7 @@ +module.exports = { + preset: "ts-jest", + testEnvironment: "node", + roots: ["/tests"], + setupFiles: ["/tests/jest.setup.ts"], + clearMocks: true, +}; diff --git a/packages/bridge/package-lock.json b/packages/bridge/package-lock.json index 0df2e30..d50bdde 100644 --- a/packages/bridge/package-lock.json +++ b/packages/bridge/package-lock.json @@ -23,11 +23,13 @@ "@types/express": "^5.0.0", "@types/jest": "^29.5.14", "@types/node": "^22.0.0", + "@types/supertest": "^7.2.0", "@types/uuid": "^10.0.0", "@types/ws": "^8.5.13", "jest": "^29.7.0", "nodemon": "^3.1.7", "prettier": "^3.8.1", + "supertest": "^7.2.2", "ts-jest": "^29.2.5", "ts-node": "^10.9.2", "typescript": "^5.6.0" @@ -1039,6 +1041,29 @@ "integrity": "sha512-GaHYm+c0O9MjZRu0ongGBRbinu8gVAMd2UZjji6jVmqKtZluZnptXGWhz1E8j8D2HJ3f/yMxKAUC0b+57wncIw==", "license": "MIT" }, + "node_modules/@noble/hashes": { + "version": "1.8.0", + "resolved": "https://registry.npmjs.org/@noble/hashes/-/hashes-1.8.0.tgz", + "integrity": "sha512-jCs9ldd7NwzpgXDIf6P3+NrHh9/sD6CQdxHyjQI+h/6rDNo88ypBxxz45UDuZHz9r3tNz7N/VInSVoVdtXEI4A==", + "dev": true, + "license": "MIT", + "engines": { + "node": "^14.21.3 || >=16" + }, + "funding": { + "url": "https://paulmillr.com/funding/" + } + }, + "node_modules/@paralleldrive/cuid2": { + "version": "2.3.1", + "resolved": "https://registry.npmjs.org/@paralleldrive/cuid2/-/cuid2-2.3.1.tgz", + "integrity": "sha512-XO7cAxhnTZl0Yggq6jOgjiOHhbgcO4NqFqwSmQpjK3b6TEE6Uj/jfSk6wzYyemh3+I0sHirKSetjQwn5cZktFw==", + "dev": true, + "license": "MIT", + "dependencies": { + "@noble/hashes": "^1.1.5" + } + }, "node_modules/@sinclair/typebox": { "version": "0.27.10", "resolved": "https://registry.npmjs.org/@sinclair/typebox/-/typebox-0.27.10.tgz", @@ -1160,6 +1185,13 @@ "@types/node": "*" } }, + "node_modules/@types/cookiejar": { + "version": "2.1.5", + "resolved": "https://registry.npmjs.org/@types/cookiejar/-/cookiejar-2.1.5.tgz", + "integrity": "sha512-he+DHOWReW0nghN24E1WUqM0efK4kI9oTqDm6XmK8ZPe2djZ90BSNdGnIyCLzCPw7/pogPlGbzI2wHGGmi4O/Q==", + "dev": true, + "license": "MIT" + }, "node_modules/@types/cors": { "version": "2.8.19", "resolved": "https://registry.npmjs.org/@types/cors/-/cors-2.8.19.tgz", @@ -1250,6 +1282,13 @@ "pretty-format": "^29.0.0" } }, + "node_modules/@types/methods": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/@types/methods/-/methods-1.1.4.tgz", + "integrity": "sha512-ymXWVrDiCxTBE3+RIrrP533E70eA+9qu7zdWoHuOmGujkYtzf4HQF96b8nwHLqhuf4ykX61IGRIB38CC6/sImQ==", + "dev": true, + "license": "MIT" + }, "node_modules/@types/node": { "version": "22.19.15", "resolved": "https://registry.npmjs.org/@types/node/-/node-22.19.15.tgz", @@ -1302,6 +1341,30 @@ "dev": true, "license": "MIT" }, + "node_modules/@types/superagent": { + "version": "8.1.9", + "resolved": "https://registry.npmjs.org/@types/superagent/-/superagent-8.1.9.tgz", + "integrity": "sha512-pTVjI73witn+9ILmoJdajHGW2jkSaOzhiFYF1Rd3EQ94kymLqB9PjD9ISg7WaALC7+dCHT0FGe9T2LktLq/3GQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "@types/cookiejar": "^2.1.5", + "@types/methods": "^1.1.4", + "@types/node": "*", + "form-data": "^4.0.0" + } + }, + "node_modules/@types/supertest": { + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/@types/supertest/-/supertest-7.2.0.tgz", + "integrity": "sha512-uh2Lv57xvggst6lCqNdFAmDSvoMG7M/HDtX4iUCquxQ5EGPtaPM5PL5Hmi7LCvOG8db7YaCPNJEeoI8s/WzIQw==", + "dev": true, + "license": "MIT", + "dependencies": { + "@types/methods": "^1.1.4", + "@types/superagent": "^8.1.0" + } + }, "node_modules/@types/uuid": { "version": "10.0.0", "resolved": "https://registry.npmjs.org/@types/uuid/-/uuid-10.0.0.tgz", @@ -1454,6 +1517,20 @@ "integrity": "sha512-PCVAQswWemu6UdxsDFFX/+gVeYqKAod3D3UVm91jHwynguOwAvYPhx8nNlM++NqRcK6CxxpUafjmhIdKiHibqg==", "license": "MIT" }, + "node_modules/asap": { + "version": "2.0.6", + "resolved": "https://registry.npmjs.org/asap/-/asap-2.0.6.tgz", + "integrity": "sha512-BSHWgDSAiKs50o2Re8ppvp3seVHXSRM44cdSsT9FfNEUUZLOGWVCsiWaRPWM1Znn+mqZ1OfVZ3z3DWEzSp7hRA==", + "dev": true, + "license": "MIT" + }, + "node_modules/asynckit": { + "version": "0.4.0", + "resolved": "https://registry.npmjs.org/asynckit/-/asynckit-0.4.0.tgz", + "integrity": "sha512-Oei9OH4tRh0YqU3GxhX79dM/mwVgvbZJaSNaRk+bshkj0S5cfHcgYakreBjrHwatXKbz+IoIdYLxrKim2MjW0Q==", + "dev": true, + "license": "MIT" + }, "node_modules/babel-jest": { "version": "29.7.0", "resolved": "https://registry.npmjs.org/babel-jest/-/babel-jest-29.7.0.tgz", @@ -1922,6 +1999,29 @@ "dev": true, "license": "MIT" }, + "node_modules/combined-stream": { + "version": "1.0.8", + "resolved": "https://registry.npmjs.org/combined-stream/-/combined-stream-1.0.8.tgz", + "integrity": "sha512-FQN4MRfuJeHf7cBbBMJFXhKSDq+2kAArBlmRBvcvFE5BB1HZKXtSFASDhdlz9zOYwxh8lDdnvmMOe/+5cdoEdg==", + "dev": true, + "license": "MIT", + "dependencies": { + "delayed-stream": "~1.0.0" + }, + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/component-emitter": { + "version": "1.3.1", + "resolved": "https://registry.npmjs.org/component-emitter/-/component-emitter-1.3.1.tgz", + "integrity": "sha512-T0+barUSQRTUQASh8bx02dl+DhF54GtIDY13Y3m9oWTklKbb3Wv974meRpeZ3lp1JpLVECWWNHC4vaG2XHXouQ==", + "dev": true, + "license": "MIT", + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, "node_modules/concat-map": { "version": "0.0.1", "resolved": "https://registry.npmjs.org/concat-map/-/concat-map-0.0.1.tgz", @@ -1972,6 +2072,13 @@ "integrity": "sha512-NXdYc3dLr47pBkpUCHtKSwIOQXLVn8dZEuywboCOJY/osA0wFSLlSawr3KN8qXJEyX66FcONTH8EIlVuK0yyFA==", "license": "MIT" }, + "node_modules/cookiejar": { + "version": "2.1.4", + "resolved": "https://registry.npmjs.org/cookiejar/-/cookiejar-2.1.4.tgz", + "integrity": "sha512-LDx6oHrK+PhzLKJU9j5S7/Y3jM/mUHvD/DeI1WQmJn652iPC5Y4TBzC9l+5OMOXlyTTA+SmVUPm0HQUwpD5Jqw==", + "dev": true, + "license": "MIT" + }, "node_modules/cors": { "version": "2.8.6", "resolved": "https://registry.npmjs.org/cors/-/cors-2.8.6.tgz", @@ -2067,6 +2174,16 @@ "node": ">=0.10.0" } }, + "node_modules/delayed-stream": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/delayed-stream/-/delayed-stream-1.0.0.tgz", + "integrity": "sha512-ZySD7Nf91aLB0RxL4KGrKHBXl7Eds1DAmEdcoVawXnLD7SDhpNgtuII2aAkg7a7QS41jxPSZ17p4VdGnMHk3MQ==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=0.4.0" + } + }, "node_modules/depd": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/depd/-/depd-2.0.0.tgz", @@ -2096,6 +2213,17 @@ "node": ">=8" } }, + "node_modules/dezalgo": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/dezalgo/-/dezalgo-1.0.4.tgz", + "integrity": "sha512-rXSP0bf+5n0Qonsb+SVVfNfIsimO4HEtmnIpPHY8Q1UCzKlQrDMfdobr8nJOOsRgWCyMRqeSBQzmWUMq7zvVig==", + "dev": true, + "license": "ISC", + "dependencies": { + "asap": "^2.0.0", + "wrappy": "1" + } + }, "node_modules/diff": { "version": "4.0.4", "resolved": "https://registry.npmjs.org/diff/-/diff-4.0.4.tgz", @@ -2224,6 +2352,22 @@ "node": ">= 0.4" } }, + "node_modules/es-set-tostringtag": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/es-set-tostringtag/-/es-set-tostringtag-2.1.0.tgz", + "integrity": "sha512-j6vWzfrGVfyXxge+O0x5sh6cvxAog0a/4Rdd2K36zCMV5eJ+/+tOAngRO8cODMNWbVRdVlmGZQL2YS3yR8bIUA==", + "dev": true, + "license": "MIT", + "dependencies": { + "es-errors": "^1.3.0", + "get-intrinsic": "^1.2.6", + "has-tostringtag": "^1.0.2", + "hasown": "^2.0.2" + }, + "engines": { + "node": ">= 0.4" + } + }, "node_modules/escalade": { "version": "3.2.0", "resolved": "https://registry.npmjs.org/escalade/-/escalade-3.2.0.tgz", @@ -2376,6 +2520,13 @@ "dev": true, "license": "MIT" }, + "node_modules/fast-safe-stringify": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/fast-safe-stringify/-/fast-safe-stringify-2.1.1.tgz", + "integrity": "sha512-W+KJc2dmILlPplD/H4K9l9LcAHAfPtP6BY84uVLXQ6Evcz9Lcg33Y2z1IVblT6xdY54PXYVHEv+0Wpq8Io6zkA==", + "dev": true, + "license": "MIT" + }, "node_modules/fb-watchman": { "version": "2.0.2", "resolved": "https://registry.npmjs.org/fb-watchman/-/fb-watchman-2.0.2.tgz", @@ -2431,6 +2582,41 @@ "node": ">=8" } }, + "node_modules/form-data": { + "version": "4.0.5", + "resolved": "https://registry.npmjs.org/form-data/-/form-data-4.0.5.tgz", + "integrity": "sha512-8RipRLol37bNs2bhoV67fiTEvdTrbMUYcFTiy3+wuuOnUog2QBHCZWXDRijWQfAkhBj2Uf5UnVaiWwA5vdd82w==", + "dev": true, + "license": "MIT", + "dependencies": { + "asynckit": "^0.4.0", + "combined-stream": "^1.0.8", + "es-set-tostringtag": "^2.1.0", + "hasown": "^2.0.2", + "mime-types": "^2.1.12" + }, + "engines": { + "node": ">= 6" + } + }, + "node_modules/formidable": { + "version": "3.5.4", + "resolved": "https://registry.npmjs.org/formidable/-/formidable-3.5.4.tgz", + "integrity": "sha512-YikH+7CUTOtP44ZTnUhR7Ic2UASBPOqmaRkRKxRbywPTe5VxF7RRCck4af9wutiZ/QKM5nME9Bie2fFaPz5Gug==", + "dev": true, + "license": "MIT", + "dependencies": { + "@paralleldrive/cuid2": "^2.2.2", + "dezalgo": "^1.0.4", + "once": "^1.4.0" + }, + "engines": { + "node": ">=14.0.0" + }, + "funding": { + "url": "https://ko-fi.com/tunnckoCore/commissions" + } + }, "node_modules/forwarded": { "version": "0.2.0", "resolved": "https://registry.npmjs.org/forwarded/-/forwarded-0.2.0.tgz", @@ -2658,6 +2844,22 @@ "url": "https://github.com/sponsors/ljharb" } }, + "node_modules/has-tostringtag": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/has-tostringtag/-/has-tostringtag-1.0.2.tgz", + "integrity": "sha512-NqADB8VjPFLM2V0VvHUewwwsw0ZWBaIdgo+ieHtK3hasLz4qeCRjYcqfB6AQrBggRKppKF8L52/VqdVsO47Dlw==", + "dev": true, + "license": "MIT", + "dependencies": { + "has-symbols": "^1.0.3" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, "node_modules/hasown": { "version": "2.0.2", "resolved": "https://registry.npmjs.org/hasown/-/hasown-2.0.2.tgz", @@ -4926,6 +5128,90 @@ "url": "https://github.com/sponsors/sindresorhus" } }, + "node_modules/superagent": { + "version": "10.3.0", + "resolved": "https://registry.npmjs.org/superagent/-/superagent-10.3.0.tgz", + "integrity": "sha512-B+4Ik7ROgVKrQsXTV0Jwp2u+PXYLSlqtDAhYnkkD+zn3yg8s/zjA2MeGayPoY/KICrbitwneDHrjSotxKL+0XQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "component-emitter": "^1.3.1", + "cookiejar": "^2.1.4", + "debug": "^4.3.7", + "fast-safe-stringify": "^2.1.1", + "form-data": "^4.0.5", + "formidable": "^3.5.4", + "methods": "^1.1.2", + "mime": "2.6.0", + "qs": "^6.14.1" + }, + "engines": { + "node": ">=14.18.0" + } + }, + "node_modules/superagent/node_modules/debug": { + "version": "4.4.3", + "resolved": "https://registry.npmjs.org/debug/-/debug-4.4.3.tgz", + "integrity": "sha512-RGwwWnwQvkVfavKVt22FGLw+xYSdzARwm0ru6DhTVA3umU5hZc28V3kO4stgYryrTlLpuvgI9GiijltAjNbcqA==", + "dev": true, + "license": "MIT", + "dependencies": { + "ms": "^2.1.3" + }, + "engines": { + "node": ">=6.0" + }, + "peerDependenciesMeta": { + "supports-color": { + "optional": true + } + } + }, + "node_modules/superagent/node_modules/mime": { + "version": "2.6.0", + "resolved": "https://registry.npmjs.org/mime/-/mime-2.6.0.tgz", + "integrity": "sha512-USPkMeET31rOMiarsBNIHZKLGgvKc/LrjofAnBlOttf5ajRvqiRA8QsenbcooctK6d6Ts6aqZXBA+XbkKthiQg==", + "dev": true, + "license": "MIT", + "bin": { + "mime": "cli.js" + }, + "engines": { + "node": ">=4.0.0" + } + }, + "node_modules/superagent/node_modules/ms": { + "version": "2.1.3", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.3.tgz", + "integrity": "sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==", + "dev": true, + "license": "MIT" + }, + "node_modules/supertest": { + "version": "7.2.2", + "resolved": "https://registry.npmjs.org/supertest/-/supertest-7.2.2.tgz", + "integrity": "sha512-oK8WG9diS3DlhdUkcFn4tkNIiIbBx9lI2ClF8K+b2/m8Eyv47LSawxUzZQSNKUrVb2KsqeTDCcjAAVPYaSLVTA==", + "dev": true, + "license": "MIT", + "dependencies": { + "cookie-signature": "^1.2.2", + "methods": "^1.1.2", + "superagent": "^10.3.0" + }, + "engines": { + "node": ">=14.18.0" + } + }, + "node_modules/supertest/node_modules/cookie-signature": { + "version": "1.2.2", + "resolved": "https://registry.npmjs.org/cookie-signature/-/cookie-signature-1.2.2.tgz", + "integrity": "sha512-D76uU73ulSXrD1UXF4KE2TMxVVwhsnCgfAyTg9k8P6KGZjlXKrOLe4dJQKI3Bxi5wjesZoFXJWElNWBjPZMbhg==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=6.6.0" + } + }, "node_modules/supports-color": { "version": "7.2.0", "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", diff --git a/packages/bridge/package.json b/packages/bridge/package.json index bdf1304..60ab1f4 100644 --- a/packages/bridge/package.json +++ b/packages/bridge/package.json @@ -31,11 +31,13 @@ "@types/express": "^5.0.0", "@types/jest": "^29.5.14", "@types/node": "^22.0.0", + "@types/supertest": "^7.2.0", "@types/uuid": "^10.0.0", "@types/ws": "^8.5.13", "jest": "^29.7.0", "nodemon": "^3.1.7", "prettier": "^3.8.1", + "supertest": "^7.2.2", "ts-jest": "^29.2.5", "ts-node": "^10.9.2", "typescript": "^5.6.0" diff --git a/packages/bridge/tests/agents/agent_sdk_adapter.test.ts b/packages/bridge/tests/agents/agent_sdk_adapter.test.ts new file mode 100644 index 0000000..f414673 --- /dev/null +++ b/packages/bridge/tests/agents/agent_sdk_adapter.test.ts @@ -0,0 +1,223 @@ +import { AgentSdkAdapter } from "../../src/agents/agent_sdk_adapter"; +import type { ConnectionManager } from "../../src/websocket/connection_manager"; +import type { BridgeMessage } from "../../src/types"; + +describe("AgentSdkAdapter", () => { + describe("handleSessionStart - resume behavior", () => { + function createMockDependencies() { + const sentMessages: Array<{ clientId: string; message: BridgeMessage }> = []; + + const connectionManager = { + sendToClient: jest.fn((clientId: string, message: BridgeMessage) => { + sentMessages.push({ clientId, message }); + }), + addSessionToClient: jest.fn(), + }; + + const sessionManager = { + createSession: jest.fn, [unknown]>(), + resumeSession: jest.fn, [string]>(), + getSession: jest.fn(), + closeSession: jest.fn(), + }; + + return { + connectionManager: connectionManager as unknown as ConnectionManager, + sessionManager, + sentMessages, + }; + } + + it("creates a new session when resume is false", async () => { + const { connectionManager, sessionManager, sentMessages } = createMockDependencies(); + + sessionManager.createSession.mockResolvedValue("new-session-id"); + sessionManager.getSession.mockReturnValue({ + id: "new-session-id", + agent: "claude-code", + title: "project", + model: "claude-opus-4-6", + working_directory: "/repo/project", + created_at: new Date().toISOString(), + status: "idle", + }); + + const adapter = new AgentSdkAdapter(sessionManager as never, connectionManager as never); + + await adapter.handleSessionStart( + { + agent: "claude-code", + working_directory: "/repo/project", + resume: false, + }, + "client-1", + "req-123", + ); + + expect(sessionManager.createSession).toHaveBeenCalledWith( + expect.objectContaining({ + agent: "claude-code", + workingDirectory: "/repo/project", + }), + ); + expect(sessionManager.resumeSession).not.toHaveBeenCalled(); + expect(connectionManager.addSessionToClient).toHaveBeenCalledWith( + "client-1", + "new-session-id", + ); + + expect(sentMessages[0]?.message).toMatchObject({ + type: "session_ready", + id: "req-123", + payload: { + session_id: "new-session-id", + agent: "claude-code", + working_directory: "/repo/project", + status: "ready", + }, + }); + }); + + it("creates a new session when resume is true but session_id is missing", async () => { + const { connectionManager, sessionManager, sentMessages } = createMockDependencies(); + + sessionManager.createSession.mockResolvedValue("new-session-id"); + sessionManager.getSession.mockReturnValue({ + id: "new-session-id", + agent: "claude-code", + title: "project", + model: "claude-opus-4-6", + working_directory: "/repo/project", + created_at: new Date().toISOString(), + status: "idle", + }); + + const adapter = new AgentSdkAdapter(sessionManager as never, connectionManager as never); + + // resume: true but no session_id provided + await adapter.handleSessionStart( + { + agent: "claude-code", + working_directory: "/repo/project", + resume: true, + // session_id is undefined/null + }, + "client-1", + "req-123", + ); + + // Should create a new session since session_id is not a valid string + expect(sessionManager.createSession).toHaveBeenCalled(); + expect(sessionManager.resumeSession).not.toHaveBeenCalled(); + }); + + it("resumes existing session when resume is true and session_id is provided", async () => { + const { connectionManager, sessionManager, sentMessages } = createMockDependencies(); + + sessionManager.resumeSession.mockResolvedValue(undefined); + sessionManager.getSession.mockReturnValue({ + id: "existing-session-id", + agent: "claude-code", + title: "resumed-project", + model: "claude-opus-4-6", + working_directory: "/repo/resumed", + created_at: new Date().toISOString(), + status: "idle", + }); + + const adapter = new AgentSdkAdapter(sessionManager as never, connectionManager as never); + + await adapter.handleSessionStart( + { + agent: "claude-code", + session_id: "existing-session-id", + working_directory: "/repo/resumed", + resume: true, + }, + "client-1", + "req-resume-1", + ); + + expect(sessionManager.resumeSession).toHaveBeenCalledWith("existing-session-id"); + expect(sessionManager.createSession).not.toHaveBeenCalled(); + expect(connectionManager.addSessionToClient).toHaveBeenCalledWith( + "client-1", + "existing-session-id", + ); + + expect(sentMessages[0]?.message).toMatchObject({ + type: "session_ready", + id: "req-resume-1", + payload: { + session_id: "existing-session-id", + agent: "claude-code", + working_directory: "/repo/resumed", + status: "ready", + }, + }); + }); + + it("sends error when resume fails for non-existent session", async () => { + const { connectionManager, sessionManager, sentMessages } = createMockDependencies(); + + sessionManager.resumeSession.mockRejectedValue( + new Error("Session not found: nonexistent-id"), + ); + + const adapter = new AgentSdkAdapter(sessionManager as never, connectionManager as never); + + await adapter.handleSessionStart( + { + agent: "claude-code", + session_id: "nonexistent-id", + resume: true, + }, + "client-1", + "req-resume-fail", + ); + + expect(sessionManager.resumeSession).toHaveBeenCalledWith("nonexistent-id"); + expect(connectionManager.addSessionToClient).not.toHaveBeenCalled(); + + expect(sentMessages[0]?.message).toMatchObject({ + type: "error", + id: "req-resume-fail", + payload: { + code: "BRIDGE_ERROR", + message: expect.stringContaining("Session not found"), + request_type: "session_start", + recoverable: false, + }, + }); + }); + + it("sends error when session not found after resume", async () => { + const { connectionManager, sessionManager, sentMessages } = createMockDependencies(); + + // Resume succeeds but session isn't found after (edge case) + sessionManager.resumeSession.mockResolvedValue(undefined); + sessionManager.getSession.mockReturnValue(undefined); + + const adapter = new AgentSdkAdapter(sessionManager as never, connectionManager as never); + + await adapter.handleSessionStart( + { + agent: "claude-code", + session_id: "ghost-session-id", + resume: true, + }, + "client-1", + "req-ghost", + ); + + expect(sentMessages[0]?.message).toMatchObject({ + type: "error", + payload: { + code: "BRIDGE_ERROR", + message: expect.stringContaining("Session not found after start"), + request_type: "session_start", + }, + }); + }); + }); +}); diff --git a/packages/bridge/tests/agents/session_manager.test.ts b/packages/bridge/tests/agents/session_manager.test.ts new file mode 100644 index 0000000..dce5f1b --- /dev/null +++ b/packages/bridge/tests/agents/session_manager.test.ts @@ -0,0 +1,324 @@ +import { AgentSessionManager } from "../../src/agents/session_manager"; +import { eventBus } from "../../src/notifications/event_bus"; +import type { + AgentRuntime, + AgentRuntimeTurnRequest, + AgentRuntimeTurnResult, +} from "../../src/agents/agent_runtime"; + +function nextTick(): Promise { + return new Promise((resolve) => { + setImmediate(resolve); + }); +} + +describe("AgentSessionManager", () => { + afterEach(() => { + eventBus.removeAllListeners(); + }); + + // ========================================================================= + // Session Resume Tests + // ========================================================================= + + describe("resumeSession", () => { + it("throws when session does not exist", async () => { + const runtime: AgentRuntime = { runTurn: jest.fn() }; + const toolExecutor = { getToolDefinitions: jest.fn(() => []), execute: jest.fn() }; + const manager = new AgentSessionManager(runtime, toolExecutor as never); + + await expect(manager.resumeSession("nonexistent-session")).rejects.toThrow( + "Session not found: nonexistent-session", + ); + }); + + it("sets session status to idle and preserves metadata", async () => { + const runtime: AgentRuntime = { runTurn: jest.fn() }; + const toolExecutor = { getToolDefinitions: jest.fn(() => []), execute: jest.fn() }; + const manager = new AgentSessionManager(runtime, toolExecutor as never); + + const sessionId = await manager.createSession({ + workingDirectory: process.cwd(), + model: "claude-opus-4-6", + }); + + // Verify session was created + const sessionBefore = manager.getSession(sessionId); + expect(sessionBefore).toBeDefined(); + expect(sessionBefore!.status).toBe("idle"); + + // Close the session + manager.closeSession(sessionId); + + // Verify session is removed and can't be resumed + await expect(manager.resumeSession(sessionId)).rejects.toThrow( + `Session not found: ${sessionId}`, + ); + }); + + it("resuming an active session sets status to idle", async () => { + const runtime: AgentRuntime = { runTurn: jest.fn() }; + const toolExecutor = { getToolDefinitions: jest.fn(() => []), execute: jest.fn() }; + const manager = new AgentSessionManager(runtime, toolExecutor as never); + + const sessionId = await manager.createSession({ + workingDirectory: process.cwd(), + model: "claude-opus-4-6", + }); + + // Verify session exists and is idle + const sessionBefore = manager.getSession(sessionId); + expect(sessionBefore).toBeDefined(); + expect(sessionBefore!.status).toBe("idle"); + + // Resume should succeed and keep it idle + await manager.resumeSession(sessionId); + + const sessionAfter = manager.getSession(sessionId); + expect(sessionAfter).toBeDefined(); + expect(sessionAfter!.status).toBe("idle"); + }); + + it("preserves session history across resume", async () => { + const runTurn = jest + .fn, [AgentRuntimeTurnRequest]>() + .mockImplementationOnce(async () => ({ + stopReason: "end_turn", + message: { + role: "assistant", + content: [{ type: "text", text: "Response" }], + }, + })); + + const runtime: AgentRuntime = { runTurn }; + const toolExecutor = { getToolDefinitions: jest.fn(() => []), execute: jest.fn() }; + const manager = new AgentSessionManager(runtime, toolExecutor as never); + + const sessionId = await manager.createSession({ + workingDirectory: process.cwd(), + model: "claude-opus-4-6", + }); + + // Send a message to populate history + await manager.sendMessage(sessionId, "First message", "client-1"); + + // Verify session is still accessible + const session = manager.getSession(sessionId); + expect(session).toBeDefined(); + + // Resume should succeed + await expect(manager.resumeSession(sessionId)).resolves.toBeUndefined(); + }); + }); + + it("waits for approval, executes the tool, and resumes the session turn", async () => { + const runTurn = jest + .fn, [AgentRuntimeTurnRequest]>() + .mockImplementationOnce(async (request) => { + request.onTextDelta?.("Planning change..."); + return { + stopReason: "tool_use", + message: { + role: "assistant", + content: [ + { type: "text", text: "Planning change..." }, + { + type: "tool_use", + id: "tool-call-1", + name: "run_command", + input: { command: "node -e console.log(1)" }, + }, + ], + }, + }; + }) + .mockImplementationOnce(async (request) => { + expect(request.messages.at(-1)).toMatchObject({ + role: "user", + content: [ + { + type: "tool_result", + tool_use_id: "tool-call-1", + is_error: false, + }, + ], + }); + + request.onTextDelta?.("Done."); + return { + stopReason: "end_turn", + message: { + role: "assistant", + content: [{ type: "text", text: "Done." }], + }, + }; + }); + + const runtime: AgentRuntime = { + runTurn, + }; + + const toolExecutor = { + getToolDefinitions: jest.fn(() => []), + execute: jest.fn(async () => ({ + success: true, + content: "command output", + durationMs: 17, + })), + }; + + const manager = new AgentSessionManager(runtime, toolExecutor as never); + const streamChunks: string[] = []; + const sessionEvents: Array> = []; + const toolEvents: Array> = []; + + eventBus.onTyped("stream-chunk", (payload) => { + streamChunks.push(String((payload as { content?: unknown }).content ?? "")); + }); + eventBus.onTyped("session-event", (payload) => { + sessionEvents.push(payload as Record); + }); + eventBus.onTyped("tool-event", (payload) => { + toolEvents.push(payload as Record); + }); + + const sessionId = await manager.createSession({ + workingDirectory: process.cwd(), + model: "claude-opus-4-6", + }); + + const sendPromise = manager.sendMessage(sessionId, "Run the command", "client-1"); + await nextTick(); + + expect(toolEvents).toContainEqual( + expect.objectContaining({ + type: "approval_required", + session_id: sessionId, + tool_call_id: "tool-call-1", + tool: "run_command", + }), + ); + + await manager.executeToolCall(sessionId, "tool-call-1", "modified", { + command: "node -e console.log(2)", + }); + await sendPromise; + + expect(toolExecutor.execute).toHaveBeenCalledWith( + "run_command", + { command: "node -e console.log(2)" }, + process.cwd(), + ); + expect(toolEvents).toContainEqual( + expect.objectContaining({ + type: "tool_result", + session_id: sessionId, + tool_call_id: "tool-call-1", + tool: "run_command", + result: expect.objectContaining({ + success: true, + content: "command output", + duration_ms: 17, + }), + }), + ); + expect(streamChunks).toEqual(["Planning change...", "Done."]); + expect(sessionEvents).toContainEqual( + expect.objectContaining({ + type: "stream_end", + session_id: sessionId, + finish_reason: "stop", + }), + ); + expect(runTurn).toHaveBeenCalledTimes(2); + }); + + it("turns rejected approvals into tool_result feedback without running the tool", async () => { + const runTurn = jest + .fn, [AgentRuntimeTurnRequest]>() + .mockImplementationOnce(async () => ({ + stopReason: "tool_use", + message: { + role: "assistant", + content: [ + { + type: "tool_use", + id: "tool-call-2", + name: "edit_file", + input: { + path: "README.md", + old_string: "old", + new_string: "new", + }, + }, + ], + }, + })) + .mockImplementationOnce(async (request) => { + expect(request.messages.at(-1)).toMatchObject({ + role: "user", + content: [ + { + type: "tool_result", + tool_use_id: "tool-call-2", + is_error: true, + content: expect.stringContaining("rejected by user"), + }, + ], + }); + + return { + stopReason: "end_turn", + message: { + role: "assistant", + content: [{ type: "text", text: "Okay, I will not apply it." }], + }, + }; + }); + + const runtime: AgentRuntime = { runTurn }; + const toolExecutor = { + getToolDefinitions: jest.fn(() => []), + execute: jest.fn(), + }; + + const manager = new AgentSessionManager(runtime, toolExecutor as never); + const toolEvents: Array> = []; + eventBus.onTyped("tool-event", (payload) => { + toolEvents.push(payload as Record); + }); + + const sessionId = await manager.createSession({ workingDirectory: process.cwd() }); + const sendPromise = manager.sendMessage(sessionId, "Try editing the file", "client-1"); + await nextTick(); + + await manager.executeToolCall(sessionId, "tool-call-2", "rejected", null); + await sendPromise; + + expect(toolExecutor.execute).not.toHaveBeenCalled(); + expect(toolEvents).toContainEqual( + expect.objectContaining({ + type: "tool_rejected", + session_id: sessionId, + tool_call_id: "tool-call-2", + }), + ); + }); + + it("rejects approval responses for unknown tool calls", async () => { + const runtime: AgentRuntime = { + runTurn: jest.fn(), + }; + + const manager = new AgentSessionManager(runtime, { + getToolDefinitions: jest.fn(() => []), + execute: jest.fn(), + } as never); + + const sessionId = await manager.createSession({ workingDirectory: process.cwd() }); + + await expect( + manager.executeToolCall(sessionId, "missing-tool-call", "approved", null), + ).rejects.toThrow("Tool call not found: missing-tool-call"); + }); +}); diff --git a/packages/bridge/tests/agents/tool_executor.test.ts b/packages/bridge/tests/agents/tool_executor.test.ts new file mode 100644 index 0000000..e804a7a --- /dev/null +++ b/packages/bridge/tests/agents/tool_executor.test.ts @@ -0,0 +1,53 @@ +import fs from "fs"; +import path from "path"; +import { ToolExecutor } from "../../src/agents/tool_executor"; + +describe("ToolExecutor", () => { + let tempDir: string; + + beforeEach(() => { + tempDir = fs.mkdtempSync(path.join(process.cwd(), "tool-executor-")); + fs.writeFileSync(path.join(tempDir, "sample.txt"), "hello world\n", "utf8"); + }); + + afterEach(() => { + fs.rmSync(tempDir, { recursive: true, force: true }); + }); + + it("supports Agent SDK style aliases and protocol tool names", async () => { + const executor = new ToolExecutor(); + + const readResult = await executor.execute("Read", { path: "sample.txt" }, tempDir); + const lsResult = await executor.execute("ls", { path: "." }, tempDir); + const commandResult = await executor.execute( + "Bash", + { command: "denied_command --flag" }, + tempDir, + ); + + expect(readResult).toMatchObject({ + success: true, + content: "hello world\n", + }); + expect(lsResult).toMatchObject({ + success: true, + content: expect.stringContaining("file\tsample.txt"), + }); + expect(commandResult).toMatchObject({ + success: false, + error: expect.stringContaining("Command not allowed: denied_command"), + }); + }); + + it("runs allowlisted protocol commands within the working directory", async () => { + const executor = new ToolExecutor(); + const commandResult = await executor.execute( + "run_command", + { command: "node -e console.log(process.cwd())" }, + tempDir, + ); + + expect(commandResult.success).toBe(true); + expect(commandResult.content.trim()).toBe(tempDir); + }); +}); diff --git a/packages/bridge/tests/hooks/event_queue.test.ts b/packages/bridge/tests/hooks/event_queue.test.ts new file mode 100644 index 0000000..756f3a9 --- /dev/null +++ b/packages/bridge/tests/hooks/event_queue.test.ts @@ -0,0 +1,49 @@ +import { EventQueue } from "../../src/hooks/event_queue"; +import type { BridgeMessage, NotificationPayload } from "../../src/types"; + +describe("EventQueue", () => { + it("replays queued messages without removing them", () => { + const queue = new EventQueue(); + const message: BridgeMessage = { + type: "claude_event", + id: "evt-1", + timestamp: new Date().toISOString(), + payload: { event_type: "SessionStart" }, + }; + + queue.enqueue(message, { sessionId: "sess-1" }); + + expect(queue.replay()).toEqual([message]); + expect(queue.size()).toBe(1); + }); + + it("acknowledges queued notifications by id", () => { + const queue = new EventQueue(); + const notification: BridgeMessage = { + type: "notification", + id: "notif-1", + timestamp: new Date().toISOString(), + payload: { + notification_id: "notif-1", + session_id: "sess-1", + notification_type: "approval_required", + title: "Approval needed", + body: "Review tool call", + priority: "high", + }, + }; + const toolResult: BridgeMessage = { + type: "tool_result", + id: "tool-1", + timestamp: new Date().toISOString(), + payload: { session_id: "sess-1" }, + }; + + queue.enqueue(notification, { sessionId: "sess-1", notificationId: "notif-1" }); + queue.enqueue(toolResult, { sessionId: "sess-1" }); + + queue.acknowledgeNotifications(["notif-1"]); + + expect(queue.replay()).toEqual([toolResult]); + }); +}); diff --git a/packages/bridge/tests/hooks/protocol_mapper.test.ts b/packages/bridge/tests/hooks/protocol_mapper.test.ts new file mode 100644 index 0000000..82d9371 --- /dev/null +++ b/packages/bridge/tests/hooks/protocol_mapper.test.ts @@ -0,0 +1,94 @@ +import { buildHookProtocolMessages } from "../../src/hooks/protocol_mapper"; +import type { HookEvent } from "../../src/types"; + +describe("buildHookProtocolMessages", () => { + it("maps PreToolUse hooks to approval_required messages", () => { + const event: HookEvent = { + event_type: "PreToolUse", + session_id: "sess-1", + timestamp: new Date().toISOString(), + payload: { + tool: "run_command", + params: { command: "flutter build apk" }, + description: "Build Android APK", + risk_level: "medium", + tool_call_id: "call-1", + }, + }; + + const messages = buildHookProtocolMessages(event); + const approvalRequired = messages.find((message) => message.type === "approval_required"); + + expect(messages[0]?.type).toBe("claude_event"); + expect(approvalRequired).toMatchObject({ + payload: { + session_id: "sess-1", + tool_call_id: "call-1", + tool: "run_command", + params: { command: "flutter build apk" }, + description: "Build Android APK", + risk_level: "medium", + source: "hooks", + }, + }); + }); + + it("maps PostToolUse hooks to tool_result messages", () => { + const event: HookEvent = { + event_type: "PostToolUse", + session_id: "sess-1", + timestamp: new Date().toISOString(), + payload: { + tool: "edit_file", + tool_call_id: "call-2", + result: { + success: true, + content: "File edited successfully", + diff: "@@ -1 +1 @@", + }, + }, + }; + + const messages = buildHookProtocolMessages(event); + const toolResult = messages.find((message) => message.type === "tool_result"); + + expect(toolResult).toMatchObject({ + payload: { + session_id: "sess-1", + tool_call_id: "call-2", + tool: "edit_file", + result: { + success: true, + content: "File edited successfully", + diff: "@@ -1 +1 @@", + }, + }, + }); + }); + + it("maps Notification hooks to notification messages with ack ids", () => { + const event: HookEvent = { + event_type: "Notification", + session_id: "sess-1", + timestamp: new Date().toISOString(), + payload: { + title: "Agent idle", + message: "Claude Code is waiting for input.", + }, + }; + + const messages = buildHookProtocolMessages(event); + const notification = messages.find((message) => message.type === "notification"); + + expect(notification).toMatchObject({ + payload: { + session_id: "sess-1", + notification_type: "agent_idle", + title: "Agent idle", + body: "Claude Code is waiting for input.", + priority: "normal", + }, + }); + expect(typeof notification?.id).toBe("string"); + }); +}); diff --git a/packages/bridge/tests/hooks/receiver.test.ts b/packages/bridge/tests/hooks/receiver.test.ts new file mode 100644 index 0000000..3bdd83f --- /dev/null +++ b/packages/bridge/tests/hooks/receiver.test.ts @@ -0,0 +1,250 @@ +import { createHooksRouter } from "../../src/hooks/receiver"; +import { EventQueue } from "../../src/hooks/event_queue"; +import type { ConnectionManager } from "../../src/websocket/connection_manager"; +import type { BridgeMessage } from "../../src/types"; +import express from "express"; +import request from "supertest"; + +function createMockConnectionManager(): { + manager: jest.Mocked; + broadcastMessages: BridgeMessage[]; +} { + const broadcastMessages: BridgeMessage[] = []; + const manager = { + sendToClient: jest.fn(), + authenticateClient: jest.fn(), + getClient: jest.fn(), + addSessionToClient: jest.fn(), + getClientsForSession: jest.fn(() => []), + broadcast: jest.fn((message: BridgeMessage) => { + broadcastMessages.push(message); + }), + }; + return { manager: manager as never, broadcastMessages }; +} + +describe("createHooksRouter", () => { + let eventQueue: EventQueue; + let mockConnectionManager: jest.Mocked; + let broadcastMessages: BridgeMessage[]; + let app: express.Application; + + beforeEach(() => { + eventQueue = new EventQueue(); + const result = createMockConnectionManager(); + mockConnectionManager = result.manager; + broadcastMessages = result.broadcastMessages; + + app = express(); + app.use(express.json()); + app.use("/hooks", createHooksRouter(eventQueue, mockConnectionManager)); + }); + + describe("POST /hooks/event", () => { + it("should accept valid hook events with valid token", async () => { + const response = await request(app) + .post("/hooks/event") + .set("Authorization", "Bearer test-hook-token") + .send({ + event_type: "SessionStart", + session_id: "sess-123", + timestamp: new Date().toISOString(), + payload: { working_directory: "/repo/project" }, + }); + + expect(response.status).toBe(200); + expect(response.body).toEqual({ received: true }); + }); + + it("should reject requests without token", async () => { + const response = await request(app).post("/hooks/event").send({ + event_type: "SessionStart", + session_id: "sess-123", + timestamp: new Date().toISOString(), + payload: {}, + }); + + expect(response.status).toBe(401); + }); + + it("should reject requests with invalid token", async () => { + const response = await request(app) + .post("/hooks/event") + .set("Authorization", "Bearer invalid-token") + .send({ + event_type: "SessionStart", + session_id: "sess-123", + timestamp: new Date().toISOString(), + payload: {}, + }); + + expect(response.status).toBe(401); + }); + + it("should reject invalid hook event shape", async () => { + const response = await request(app) + .post("/hooks/event") + .set("Authorization", "Bearer test-hook-token") + .send({ + event_type: "InvalidEventType", + session_id: "sess-123", + timestamp: new Date().toISOString(), + payload: {}, + }); + + expect(response.status).toBe(400); + expect(response.body.error).toBe("Bad Request"); + }); + + it("should reject stale timestamps", async () => { + const staleTimestamp = new Date(Date.now() - 10 * 60 * 1000).toISOString(); + const response = await request(app) + .post("/hooks/event") + .set("Authorization", "Bearer test-hook-token") + .send({ + event_type: "SessionStart", + session_id: "sess-123", + timestamp: staleTimestamp, + payload: {}, + }); + + expect(response.status).toBe(400); + }); + + it("should enqueue events after validation", async () => { + const initialSize = eventQueue.size(); + + await request(app) + .post("/hooks/event") + .set("Authorization", "Bearer test-hook-token") + .send({ + event_type: "SessionStart", + session_id: "sess-123", + timestamp: new Date().toISOString(), + payload: { working_directory: "/repo/project" }, + }); + + expect(eventQueue.size()).toBe(initialSize + 1); + }); + + it("should broadcast events to connected clients", async () => { + await request(app) + .post("/hooks/event") + .set("Authorization", "Bearer test-hook-token") + .send({ + event_type: "SessionStart", + session_id: "sess-123", + timestamp: new Date().toISOString(), + payload: { working_directory: "/repo/project" }, + }); + + expect(mockConnectionManager.broadcast).toHaveBeenCalled(); + }); + + it("should handle UserPromptSubmit events", async () => { + const response = await request(app) + .post("/hooks/event") + .set("Authorization", "Bearer test-hook-token") + .send({ + event_type: "UserPromptSubmit", + session_id: "sess-456", + timestamp: new Date().toISOString(), + payload: { + prompt: "Write a function that sorts an array", + }, + }); + + expect(response.status).toBe(200); + }); + + it("should handle PostToolUse events", async () => { + const response = await request(app) + .post("/hooks/event") + .set("Authorization", "Bearer test-hook-token") + .send({ + event_type: "PostToolUse", + session_id: "sess-789", + timestamp: new Date().toISOString(), + payload: { + tool: "read", + params: { path: "/src/index.ts" }, + result: "file contents", + }, + }); + + expect(response.status).toBe(200); + }); + + it("should handle PreToolUse events", async () => { + const response = await request(app) + .post("/hooks/event") + .set("Authorization", "Bearer test-hook-token") + .send({ + event_type: "PreToolUse", + session_id: "sess-123", + timestamp: new Date().toISOString(), + payload: { + tool: "write", + params: { path: "/src/new.ts" }, + }, + }); + + expect(response.status).toBe(200); + }); + + it("should handle SessionEnd events", async () => { + const response = await request(app) + .post("/hooks/event") + .set("Authorization", "Bearer test-hook-token") + .send({ + event_type: "SessionEnd", + session_id: "sess-123", + timestamp: new Date().toISOString(), + payload: { + reason: "completed", + }, + }); + + expect(response.status).toBe(200); + }); + + it("should handle Notification events", async () => { + const response = await request(app) + .post("/hooks/event") + .set("Authorization", "Bearer test-hook-token") + .send({ + event_type: "Notification", + session_id: "sess-123", + timestamp: new Date().toISOString(), + payload: { + notification_type: "info", + title: "Test notification", + body: "Test message", + }, + }); + + expect(response.status).toBe(200); + }); + }); + + describe("session routing", () => { + it("should route events by session_id", async () => { + await request(app).post("/hooks/event").set("Authorization", "Bearer test-hook-token").send({ + event_type: "SessionStart", + session_id: "specific-session-123", + timestamp: new Date().toISOString(), + payload: {}, + }); + + const messages = eventQueue.replay(); + expect(messages).toHaveLength(1); + + // Replay with session ID filter + const sessionMessages = eventQueue.replay("specific-session-123"); + expect(sessionMessages).toHaveLength(1); + + const otherMessages = eventQueue.replay("other-session"); + expect(otherMessages).toHaveLength(0); + }); + }); +}); diff --git a/packages/bridge/tests/hooks/validator.test.ts b/packages/bridge/tests/hooks/validator.test.ts new file mode 100644 index 0000000..c412eec --- /dev/null +++ b/packages/bridge/tests/hooks/validator.test.ts @@ -0,0 +1,28 @@ +import { validateHookEvent } from "../../src/hooks/validator"; +import type { HookEvent } from "../../src/types"; + +function createEvent(eventType: string, timestamp = new Date().toISOString()): HookEvent { + return { + event_type: eventType, + session_id: "sess-123", + timestamp, + payload: { example: true }, + }; +} + +describe("validateHookEvent", () => { + it("accepts documented hook events", () => { + expect(validateHookEvent(createEvent("SessionStart"))).toBe(true); + expect(validateHookEvent(createEvent("UserPromptSubmit"))).toBe(true); + expect(validateHookEvent(createEvent("PostToolUse"))).toBe(true); + }); + + it("rejects unsupported event types", () => { + expect(validateHookEvent(createEvent("UnknownEvent"))).toBe(false); + }); + + it("rejects stale timestamps", () => { + const staleTimestamp = new Date(Date.now() - 10 * 60 * 1000).toISOString(); + expect(validateHookEvent(createEvent("SessionEnd", staleTimestamp))).toBe(false); + }); +}); diff --git a/packages/bridge/tests/jest.setup.ts b/packages/bridge/tests/jest.setup.ts new file mode 100644 index 0000000..9057fcf --- /dev/null +++ b/packages/bridge/tests/jest.setup.ts @@ -0,0 +1,5 @@ +process.env.BRIDGE_TOKEN = "test-bridge-token"; +process.env.HOOK_TOKEN = "test-hook-token"; +process.env.ANTHROPIC_API_KEY = "test-anthropic-key"; +process.env.AGENT_MODEL = "claude-opus-4-6"; +process.env.ALLOWED_PROJECT_ROOT = process.cwd(); diff --git a/packages/bridge/tests/notifications/dispatcher.test.ts b/packages/bridge/tests/notifications/dispatcher.test.ts new file mode 100644 index 0000000..150da9f --- /dev/null +++ b/packages/bridge/tests/notifications/dispatcher.test.ts @@ -0,0 +1,113 @@ +import { EventQueue } from "../../src/hooks/event_queue"; +import { Dispatcher } from "../../src/notifications/dispatcher"; +import { eventBus } from "../../src/notifications/event_bus"; +import type { BridgeMessage, MobileClient } from "../../src/types"; + +describe("Dispatcher", () => { + afterEach(() => { + eventBus.removeAllListeners(); + }); + + it("forwards stream lifecycle, approval, and tool result events to session clients", () => { + const sentMessages: BridgeMessage[] = []; + const eventQueue = new EventQueue(); + const connectionManager = { + getClientsForSession: jest.fn((_sessionId: string): MobileClient[] => [ + { + id: "client-1", + authenticated: true, + sessionIds: ["sess-1"], + ws: {} as never, + }, + ]), + sendToClient: jest.fn((_clientId: string, message: BridgeMessage) => { + sentMessages.push(message); + }), + broadcast: jest.fn(), + }; + + new Dispatcher(connectionManager as never, eventQueue); + + eventBus.emitTyped("session-event", { + type: "stream_start", + session_id: "sess-1", + message_id: "msg-1", + }); + eventBus.emitTyped("stream-chunk", { + session_id: "sess-1", + message_id: "msg-1", + content: "Hello", + }); + eventBus.emitTyped("tool-event", { + type: "approval_required", + session_id: "sess-1", + tool_call_id: "tool-1", + tool: "run_command", + params: { command: "npm test" }, + description: "Run tests", + risk_level: "medium", + source: "agent_sdk", + }); + eventBus.emitTyped("tool-event", { + type: "tool_result", + session_id: "sess-1", + tool_call_id: "tool-1", + tool: "run_command", + result: { + success: true, + content: "Tests passed", + duration_ms: 42, + }, + }); + eventBus.emitTyped("session-event", { + type: "stream_end", + session_id: "sess-1", + message_id: "msg-1", + finish_reason: "stop", + }); + + expect(sentMessages.map((message) => message.type)).toEqual([ + "stream_start", + "stream_chunk", + "approval_required", + "tool_result", + "stream_end", + ]); + expect(sentMessages[1]).toMatchObject({ + payload: { + session_id: "sess-1", + message_id: "msg-1", + content: "Hello", + is_tool_use: false, + }, + }); + expect(sentMessages[2]).toMatchObject({ + payload: { + tool: "run_command", + params: { command: "npm test" }, + source: "agent_sdk", + }, + }); + expect(sentMessages[3]).toMatchObject({ + payload: { + tool: "run_command", + result: { + success: true, + content: "Tests passed", + duration_ms: 42, + }, + }, + }); + expect(eventQueue.size()).toBe(1); + expect(eventQueue.replay("sess-1")).toEqual([ + expect.objectContaining({ + type: "tool_result", + payload: expect.objectContaining({ + session_id: "sess-1", + tool_call_id: "tool-1", + tool: "run_command", + }), + }), + ]); + }); +}); diff --git a/packages/bridge/tests/websocket/connection_manager.test.ts b/packages/bridge/tests/websocket/connection_manager.test.ts new file mode 100644 index 0000000..7965438 --- /dev/null +++ b/packages/bridge/tests/websocket/connection_manager.test.ts @@ -0,0 +1,287 @@ +import { ConnectionManager } from "../../src/websocket/connection_manager"; +import type { MobileClient, BridgeMessage } from "../../src/types"; + +function createMockWebSocket(readyState: number = 1): { + ws: { readyState: number; send: jest.Mock }; +} { + return { + ws: { + readyState, + send: jest.fn(), + }, + }; +} + +describe("ConnectionManager", () => { + let connectionManager: ConnectionManager; + + beforeEach(() => { + connectionManager = new ConnectionManager(); + }); + + describe("addClient", () => { + it("should add a client with unauthenticated state", () => { + const { ws } = createMockWebSocket(); + connectionManager.addClient("client-1", ws as never); + + const client = connectionManager.getClient("client-1"); + expect(client).toBeDefined(); + expect(client?.id).toBe("client-1"); + expect(client?.authenticated).toBe(false); + expect(client?.sessionIds).toEqual([]); + }); + + it("should allow adding multiple clients", () => { + const { ws: ws1 } = createMockWebSocket(); + const { ws: ws2 } = createMockWebSocket(); + + connectionManager.addClient("client-1", ws1 as never); + connectionManager.addClient("client-2", ws2 as never); + + expect(connectionManager.getClient("client-1")).toBeDefined(); + expect(connectionManager.getClient("client-2")).toBeDefined(); + }); + }); + + describe("authenticateClient", () => { + it("should mark an existing client as authenticated", () => { + const { ws } = createMockWebSocket(); + connectionManager.addClient("client-1", ws as never); + connectionManager.authenticateClient("client-1"); + + const client = connectionManager.getClient("client-1"); + expect(client?.authenticated).toBe(true); + }); + + it("should do nothing for non-existent client", () => { + // Should not throw + expect(() => connectionManager.authenticateClient("unknown-client")).not.toThrow(); + }); + }); + + describe("removeClient", () => { + it("should remove an existing client", () => { + const { ws } = createMockWebSocket(); + connectionManager.addClient("client-1", ws as never); + connectionManager.removeClient("client-1"); + + expect(connectionManager.getClient("client-1")).toBeUndefined(); + }); + + it("should do nothing for non-existent client", () => { + // Should not throw + expect(() => connectionManager.removeClient("unknown-client")).not.toThrow(); + }); + }); + + describe("getClient", () => { + it("should return undefined for non-existent client", () => { + expect(connectionManager.getClient("unknown")).toBeUndefined(); + }); + + it("should return the client when it exists", () => { + const { ws } = createMockWebSocket(); + connectionManager.addClient("client-1", ws as never); + + const client = connectionManager.getClient("client-1"); + expect(client?.id).toBe("client-1"); + }); + }); + + describe("addSessionToClient", () => { + it("should add a session to client's session list", () => { + const { ws } = createMockWebSocket(); + connectionManager.addClient("client-1", ws as never); + connectionManager.addSessionToClient("client-1", "sess-1"); + + const client = connectionManager.getClient("client-1"); + expect(client?.sessionIds).toContain("sess-1"); + }); + + it("should not duplicate sessions", () => { + const { ws } = createMockWebSocket(); + connectionManager.addClient("client-1", ws as never); + connectionManager.addSessionToClient("client-1", "sess-1"); + connectionManager.addSessionToClient("client-1", "sess-1"); + + const client = connectionManager.getClient("client-1"); + expect(client?.sessionIds.filter((id) => id === "sess-1")).toHaveLength(1); + }); + + it("should do nothing for non-existent client", () => { + // Should not throw + expect(() => connectionManager.addSessionToClient("unknown", "sess-1")).not.toThrow(); + }); + }); + + describe("getClientsForSession", () => { + it("should return clients subscribed to the session", () => { + const { ws: ws1 } = createMockWebSocket(); + const { ws: ws2 } = createMockWebSocket(); + + connectionManager.addClient("client-1", ws1 as never); + connectionManager.addClient("client-2", ws2 as never); + + connectionManager.authenticateClient("client-1"); + connectionManager.authenticateClient("client-2"); + + connectionManager.addSessionToClient("client-1", "sess-1"); + connectionManager.addSessionToClient("client-2", "sess-1"); + + const clients = connectionManager.getClientsForSession("sess-1"); + expect(clients).toHaveLength(2); + expect(clients.map((c) => c.id)).toContain("client-1"); + expect(clients.map((c) => c.id)).toContain("client-2"); + }); + + it("should not return unauthenticated clients", () => { + const { ws } = createMockWebSocket(); + connectionManager.addClient("client-1", ws as never); + // Not authenticated + connectionManager.addSessionToClient("client-1", "sess-1"); + + const clients = connectionManager.getClientsForSession("sess-1"); + expect(clients).toHaveLength(0); + }); + + it("should return empty array for session with no subscribers", () => { + const clients = connectionManager.getClientsForSession("unknown-session"); + expect(clients).toEqual([]); + }); + }); + + describe("broadcast", () => { + it("should send message to all authenticated clients", () => { + const { ws: ws1 } = createMockWebSocket(); + const { ws: ws2 } = createMockWebSocket(); + + connectionManager.addClient("client-1", ws1 as never); + connectionManager.addClient("client-2", ws2 as never); + + connectionManager.authenticateClient("client-1"); + connectionManager.authenticateClient("client-2"); + + const message: BridgeMessage = { + type: "test_event", + timestamp: new Date().toISOString(), + payload: { data: "test" }, + }; + + connectionManager.broadcast(message); + + expect(ws1.send).toHaveBeenCalledTimes(1); + expect(ws2.send).toHaveBeenCalledTimes(1); + }); + + it("should not send to unauthenticated clients", () => { + const { ws } = createMockWebSocket(); + connectionManager.addClient("client-1", ws as never); + // Not authenticated + + const message: BridgeMessage = { + type: "test_event", + timestamp: new Date().toISOString(), + payload: { data: "test" }, + }; + + connectionManager.broadcast(message); + expect(ws.send).not.toHaveBeenCalled(); + }); + + it("should respect filter function", () => { + const { ws: ws1 } = createMockWebSocket(); + const { ws: ws2 } = createMockWebSocket(); + + connectionManager.addClient("client-1", ws1 as never); + connectionManager.addClient("client-2", ws2 as never); + + connectionManager.authenticateClient("client-1"); + connectionManager.authenticateClient("client-2"); + + connectionManager.addSessionToClient("client-1", "sess-1"); + connectionManager.addSessionToClient("client-2", "sess-2"); + + const message: BridgeMessage = { + type: "test_event", + timestamp: new Date().toISOString(), + payload: { data: "test" }, + }; + + // Only send to clients subscribed to sess-1 + connectionManager.broadcast(message, (client) => client.sessionIds.includes("sess-1")); + + expect(ws1.send).toHaveBeenCalledTimes(1); + expect(ws2.send).not.toHaveBeenCalled(); + }); + + it("should not send to clients with closed WebSocket", () => { + const { ws: ws1 } = createMockWebSocket(1); // OPEN + const { ws: ws2 } = createMockWebSocket(3); // CLOSED + + connectionManager.addClient("client-1", ws1 as never); + connectionManager.addClient("client-2", ws2 as never); + + connectionManager.authenticateClient("client-1"); + connectionManager.authenticateClient("client-2"); + + const message: BridgeMessage = { + type: "test_event", + timestamp: new Date().toISOString(), + payload: { data: "test" }, + }; + + connectionManager.broadcast(message); + + expect(ws1.send).toHaveBeenCalledTimes(1); + expect(ws2.send).not.toHaveBeenCalled(); + }); + }); + + describe("sendToClient", () => { + it("should send message to specific client", () => { + const { ws } = createMockWebSocket(); + connectionManager.addClient("client-1", ws as never); + connectionManager.authenticateClient("client-1"); + + const message: BridgeMessage = { + type: "test_event", + id: "msg-1", + timestamp: new Date().toISOString(), + payload: { data: "test" }, + }; + + connectionManager.sendToClient("client-1", message); + + expect(ws.send).toHaveBeenCalledTimes(1); + const sentData = JSON.parse(ws.send.mock.calls[0][0]); + expect(sentData.type).toBe("test_event"); + expect(sentData.id).toBe("msg-1"); + }); + + it("should do nothing for non-existent client", () => { + const message: BridgeMessage = { + type: "test_event", + timestamp: new Date().toISOString(), + payload: { data: "test" }, + }; + + // Should not throw + expect(() => connectionManager.sendToClient("unknown", message)).not.toThrow(); + }); + + it("should not send if WebSocket is not open", () => { + const { ws } = createMockWebSocket(0); // CONNECTING + connectionManager.addClient("client-1", ws as never); + connectionManager.authenticateClient("client-1"); + + const message: BridgeMessage = { + type: "test_event", + timestamp: new Date().toISOString(), + payload: { data: "test" }, + }; + + connectionManager.sendToClient("client-1", message); + expect(ws.send).not.toHaveBeenCalled(); + }); + }); +}); diff --git a/packages/bridge/tests/websocket/message_handler.test.ts b/packages/bridge/tests/websocket/message_handler.test.ts new file mode 100644 index 0000000..1becc1a --- /dev/null +++ b/packages/bridge/tests/websocket/message_handler.test.ts @@ -0,0 +1,255 @@ +import { EventQueue } from "../../src/hooks/event_queue"; +import { Dispatcher } from "../../src/notifications/dispatcher"; +import { eventBus } from "../../src/notifications/event_bus"; +import { MessageHandler } from "../../src/websocket/message_handler"; +import type { + AgentSession, + BridgeMessage, + NotificationPayload, + SessionStartPayload, +} from "../../src/types"; + +describe("MessageHandler", () => { + afterEach(() => { + eventBus.removeAllListeners(); + }); + + function createDependencies() { + const sentMessages: Array<{ clientId: string; message: BridgeMessage }> = []; + const connectionManager = { + sendToClient: jest.fn((clientId: string, message: BridgeMessage) => { + sentMessages.push({ clientId, message }); + }), + authenticateClient: jest.fn(), + getClient: jest.fn(), + addSessionToClient: jest.fn(), + getClientsForSession: jest.fn(), + broadcast: jest.fn(), + }; + + const agentSdkAdapter = { + handleSessionStart: jest.fn(), + handleMessage: jest.fn(), + handleApprovalResponse: jest.fn(), + handleSessionEnd: jest.fn(), + }; + + const activeSession: AgentSession = { + id: "sess-1", + agent: "claude-code", + title: "project", + model: "claude-opus-4-6", + working_directory: "/repo/project", + created_at: new Date().toISOString(), + status: "idle", + }; + + const agentSessionManager = { + getActiveSessions: jest.fn(() => [activeSession]), + }; + + const gitService = { + getStatus: jest.fn(), + commit: jest.fn(), + getDiff: jest.fn(), + }; + + const queuedNotification: BridgeMessage = { + type: "notification", + id: "notif-1", + timestamp: new Date().toISOString(), + payload: { + notification_id: "notif-1", + session_id: "sess-1", + notification_type: "approval_required", + title: "Approval needed", + body: "Review tool call", + priority: "high", + }, + }; + + const eventQueue = { + replay: jest.fn(() => [queuedNotification]), + acknowledgeNotifications: jest.fn(), + }; + + const handler = new MessageHandler( + connectionManager as never, + agentSdkAdapter as never, + agentSessionManager as never, + gitService as never, + eventQueue as never, + ); + + return { + handler, + sentMessages, + connectionManager, + agentSdkAdapter, + activeSession, + eventQueue, + }; + } + + it("sends a contract-aligned connection_ack and replays queued events on auth", async () => { + const { handler, sentMessages, connectionManager, activeSession } = createDependencies(); + + await handler.handle( + "client-1", + JSON.stringify({ + type: "auth", + id: "auth-1", + timestamp: new Date().toISOString(), + payload: { + token: "test-bridge-token", + client_version: "1.0.0", + platform: "ios", + }, + }), + ); + + expect(connectionManager.authenticateClient).toHaveBeenCalledWith("client-1"); + expect(sentMessages[0]?.message).toMatchObject({ + type: "connection_ack", + id: "auth-1", + timestamp: expect.any(String), + payload: { + server_version: "0.1.0", + supported_agents: ["claude-code"], + active_sessions: [ + { + session_id: activeSession.id, + agent: "claude-code", + title: activeSession.title, + working_directory: activeSession.working_directory, + status: activeSession.status, + }, + ], + }, + }); + expect(sentMessages[1]?.message.type).toBe("notification"); + }); + + it("passes the original request id through session_start handling", async () => { + const { handler, connectionManager, agentSdkAdapter } = createDependencies(); + connectionManager.getClient.mockReturnValue({ authenticated: true, sessionIds: [] }); + + const payload: SessionStartPayload = { + agent: "claude-code", + working_directory: "/repo/project", + resume: false, + }; + + await handler.handle( + "client-1", + JSON.stringify({ + type: "session_start", + id: "req-1", + timestamp: new Date().toISOString(), + payload, + }), + ); + + expect(agentSdkAdapter.handleSessionStart).toHaveBeenCalledWith(payload, "client-1", "req-1"); + }); + + it("acknowledges notification ids from the client", async () => { + const { handler, connectionManager, eventQueue } = createDependencies(); + connectionManager.getClient.mockReturnValue({ authenticated: true, sessionIds: [] }); + + await handler.handle( + "client-1", + JSON.stringify({ + type: "notification_ack", + timestamp: new Date().toISOString(), + payload: { + notification_ids: ["notif-1", "notif-2"], + }, + }), + ); + + expect(eventQueue.acknowledgeNotifications).toHaveBeenCalledWith(["notif-1", "notif-2"]); + }); + + it("replays queued agent-sdk tool results after auth reconnect", async () => { + const sentMessages: Array<{ clientId: string; message: BridgeMessage }> = []; + const eventQueue = new EventQueue(); + const connectionManager = { + sendToClient: jest.fn((clientId: string, message: BridgeMessage) => { + sentMessages.push({ clientId, message }); + }), + authenticateClient: jest.fn(), + getClient: jest.fn(), + addSessionToClient: jest.fn(), + getClientsForSession: jest.fn(() => []), + broadcast: jest.fn(), + }; + const agentSdkAdapter = { + handleSessionStart: jest.fn(), + handleMessage: jest.fn(), + handleApprovalResponse: jest.fn(), + handleSessionEnd: jest.fn(), + }; + const agentSessionManager = { + getActiveSessions: jest.fn(() => []), + }; + const gitService = { + getStatus: jest.fn(), + commit: jest.fn(), + getDiff: jest.fn(), + }; + + new Dispatcher(connectionManager as never, eventQueue); + eventBus.emitTyped("tool-event", { + type: "tool_result", + session_id: "sess-1", + tool_call_id: "tool-1", + tool: "run_command", + result: { + success: true, + content: "Tests passed", + duration_ms: 42, + }, + }); + + const handler = new MessageHandler( + connectionManager as never, + agentSdkAdapter as never, + agentSessionManager as never, + gitService as never, + eventQueue, + ); + + await handler.handle( + "client-1", + JSON.stringify({ + type: "auth", + id: "auth-reconnect-1", + timestamp: new Date().toISOString(), + payload: { + token: "test-bridge-token", + client_version: "1.0.0", + platform: "ios", + }, + }), + ); + + expect(sentMessages.map((entry) => entry.message.type)).toEqual([ + "connection_ack", + "tool_result", + ]); + expect(sentMessages[1]?.message).toMatchObject({ + type: "tool_result", + payload: { + session_id: "sess-1", + tool_call_id: "tool-1", + tool: "run_command", + result: { + success: true, + content: "Tests passed", + duration_ms: 42, + }, + }, + }); + }); +}); From 2c0da716f3ce2b5d722bd3b58c2e6c651caa6fd2 Mon Sep 17 00:00:00 2001 From: MasuRii Date: Fri, 20 Mar 2026 12:57:19 +0800 Subject: [PATCH 19/22] chore(mobile): add flutter_svg dependency for branding assets Add flutter_svg package to support SVG logo rendering. Update dependency resolution for vector graphics support. --- apps/mobile/pubspec.lock | 56 ++++++++++++++++++++++++++++++++++------ apps/mobile/pubspec.yaml | 3 +++ 2 files changed, 51 insertions(+), 8 deletions(-) diff --git a/apps/mobile/pubspec.lock b/apps/mobile/pubspec.lock index 9694d86..ee2fb9e 100644 --- a/apps/mobile/pubspec.lock +++ b/apps/mobile/pubspec.lock @@ -117,10 +117,10 @@ packages: dependency: transitive description: name: characters - sha256: faf38497bda5ead2a8c7615f4f7939df04333478bf32e4173fcb06d428b5716b + sha256: f71061c654a3380576a52b451dd5532377954cf9dbd272a78fc8479606670803 url: "https://pub.dev" source: hosted - version: "1.4.1" + version: "1.4.0" charcode: dependency: transitive description: @@ -403,6 +403,14 @@ packages: url: "https://pub.dev" source: hosted version: "3.1.2" + flutter_svg: + dependency: "direct main" + description: + name: flutter_svg + sha256: "1ded017b39c8e15c8948ea855070a5ff8ff8b3d5e83f3446e02d6bb12add7ad9" + url: "https://pub.dev" + source: hosted + version: "2.2.4" flutter_test: dependency: "direct dev" description: flutter @@ -619,18 +627,18 @@ packages: dependency: transitive description: name: matcher - sha256: dc0b7dc7651697ea4ff3e69ef44b0407ea32c487a39fff6a4004fa585e901861 + sha256: dc58c723c3c24bf8d3e2d3ad3f2f9d7bd9cf43ec6feaa64181775e60190153f2 url: "https://pub.dev" source: hosted - version: "0.12.19" + version: "0.12.17" material_color_utilities: dependency: transitive description: name: material_color_utilities - sha256: "9c337007e82b1889149c82ed242ed1cb24a66044e30979c44912381e9be4c48b" + sha256: f7142bb1154231d7ea5f96bc7bde4bda2a0945d2806bb11670e30b850d56bdec url: "https://pub.dev" source: hosted - version: "0.13.0" + version: "0.11.1" meta: dependency: transitive description: @@ -711,6 +719,14 @@ packages: url: "https://pub.dev" source: hosted version: "1.9.1" + path_parsing: + dependency: transitive + description: + name: path_parsing + sha256: "883402936929eac138ee0a45da5b0f2c80f89913e6dc3bf77eb65b84b409c6ca" + url: "https://pub.dev" + source: hosted + version: "1.1.0" path_provider: dependency: transitive description: @@ -1056,10 +1072,10 @@ packages: dependency: transitive description: name: test_api - sha256: "8161c84903fd860b26bfdefb7963b3f0b68fee7adea0f59ef805ecca346f0c7a" + sha256: ab2726c1a94d3176a45960b6234466ec367179b87dd74f1611adb1f3b5fb9d55 url: "https://pub.dev" source: hosted - version: "0.7.10" + version: "0.7.7" timezone: dependency: transitive description: @@ -1092,6 +1108,30 @@ packages: url: "https://pub.dev" source: hosted version: "4.5.3" + vector_graphics: + dependency: transitive + description: + name: vector_graphics + sha256: "7076216a10d5c390315fbe536a30f1254c341e7543e6c4c8a815e591307772b1" + url: "https://pub.dev" + source: hosted + version: "1.1.20" + vector_graphics_codec: + dependency: transitive + description: + name: vector_graphics_codec + sha256: "99fd9fbd34d9f9a32efd7b6a6aae14125d8237b10403b422a6a6dfeac2806146" + url: "https://pub.dev" + source: hosted + version: "1.1.13" + vector_graphics_compiler: + dependency: transitive + description: + name: vector_graphics_compiler + sha256: "5a88dd14c0954a5398af544651c7fb51b457a2a556949bfb25369b210ef73a74" + url: "https://pub.dev" + source: hosted + version: "1.2.0" vector_math: dependency: transitive description: diff --git a/apps/mobile/pubspec.yaml b/apps/mobile/pubspec.yaml index 5999c73..d271bd8 100644 --- a/apps/mobile/pubspec.yaml +++ b/apps/mobile/pubspec.yaml @@ -51,6 +51,9 @@ dependencies: # Crash reporting sentry_flutter: ^9.14.0 + # SVG support + flutter_svg: ^2.0.10 + # Utilities uuid: ^4.4.0 intl: ^0.19.0 From 7bb6309863ebd95d288681b43eba722fc0e6f402 Mon Sep 17 00:00:00 2001 From: MasuRii Date: Fri, 20 Mar 2026 12:58:01 +0800 Subject: [PATCH 20/22] test(mobile): add unit and integration tests for core features Add unit tests for network, storage, sync, and chat modules. Add integration tests for app startup and chat workflows. Update widget tests for new navigation structure. - Add tests/core/network/* for websocket and connection tests - Add tests/core/sync/* for sync queue tests - Add tests/features/chat/* for chat provider tests - Add tests/features/startup/* for startup controller tests - Add router_test.dart for navigation testing - Update integration_test/app_test.dart and chat_test.dart - Update widget_test.dart for new app structure --- apps/mobile/integration_test/app_test.dart | 108 +++++-- apps/mobile/integration_test/chat_test.dart | 121 +++++++- .../bridge_connection_validator_test.dart | 102 +++++++ .../core/network/websocket_service_test.dart | 181 ++++++++++++ .../test/core/sync/sync_queue_test.dart | 179 ++++++++++++ .../features/chat/chat_provider_test.dart | 270 ++++++++++++++++++ .../test/features/chat/tool_card_test.dart | 218 ++++++++++++++ .../bridge_startup_controller_test.dart | 144 ++++++++++ apps/mobile/test/router_test.dart | 59 ++++ apps/mobile/test/widget_test.dart | 78 ++++- 10 files changed, 1414 insertions(+), 46 deletions(-) create mode 100644 apps/mobile/test/core/network/bridge_connection_validator_test.dart create mode 100644 apps/mobile/test/core/network/websocket_service_test.dart create mode 100644 apps/mobile/test/core/sync/sync_queue_test.dart create mode 100644 apps/mobile/test/features/chat/chat_provider_test.dart create mode 100644 apps/mobile/test/features/chat/tool_card_test.dart create mode 100644 apps/mobile/test/features/startup/bridge_startup_controller_test.dart create mode 100644 apps/mobile/test/router_test.dart diff --git a/apps/mobile/integration_test/app_test.dart b/apps/mobile/integration_test/app_test.dart index 8f971c4..43f480b 100644 --- a/apps/mobile/integration_test/app_test.dart +++ b/apps/mobile/integration_test/app_test.dart @@ -1,36 +1,90 @@ import 'package:flutter/material.dart'; +import 'package:flutter_riverpod/flutter_riverpod.dart'; +import 'package:flutter_secure_storage/flutter_secure_storage.dart'; import 'package:flutter_test/flutter_test.dart'; -import 'package:recursor_mobile/main.dart' as app; +import 'package:integration_test/integration_test.dart'; +import 'package:recursor_mobile/app.dart'; +import 'package:recursor_mobile/core/network/websocket_service.dart'; +import 'package:recursor_mobile/core/providers/theme_provider.dart'; +import 'package:recursor_mobile/core/providers/token_storage_provider.dart'; +import 'package:recursor_mobile/core/storage/preferences.dart'; +import 'package:recursor_mobile/core/storage/secure_token_storage.dart'; +import 'package:recursor_mobile/features/startup/domain/bridge_startup_controller.dart'; void main() { - testWidgets('App launches and shows splash screen', (tester) async { - app.main(); - await tester.pumpAndSettle(); - // Should see splash screen - expect(find.byKey(const Key('splashScreen')), findsOneWidget); - }); + IntegrationTestWidgetsFlutterBinding.ensureInitialized(); - testWidgets('Login screen shows GitHub and PAT options', (tester) async { - app.main(); - await tester.pumpAndSettle(); - await tester.pumpAndSettle(const Duration(seconds: 2)); - // Navigate to login - expect(find.text('Sign in with GitHub'), findsOneWidget); - expect(find.text('Personal Access Token'), findsOneWidget); - }); + testWidgets('launch routes to bridge setup without any login workflow', ( + tester, + ) async { + final preferences = FakeAppPreferences(); + final tokenStorage = FakeSecureTokenStorage(); + final startupController = FakeBridgeStartupController( + const AppStartupResult.bridgeSetup(), + ); - testWidgets('PAT field accepts input', (tester) async { - app.main(); + await tester.pumpWidget( + ProviderScope( + overrides: [ + appPreferencesProvider.overrideWithValue(preferences), + tokenStorageProvider.overrideWithValue(tokenStorage), + bridgeStartupControllerProvider.overrideWithValue(startupController), + ], + child: const ReCursorApp(), + ), + ); + await tester.pump(); + await tester.pump(const Duration(milliseconds: 1300)); await tester.pumpAndSettle(); - await tester.pumpAndSettle(const Duration(seconds: 2)); - // Find PAT field and enter token - final patButton = find.text('Personal Access Token'); - if (patButton.evaluate().isNotEmpty) { - await tester.tap(patButton); - await tester.pumpAndSettle(); - await tester.enterText( - find.byKey(const Key('patTextField')), 'test-token-123'); - expect(find.byKey(const Key('patTextField')), findsOneWidget); - } + + expect(find.byKey(const Key('bridgeSetupScreen')), findsOneWidget); + expect(find.text('Bridge Setup'), findsOneWidget); + expect(find.textContaining('Sign in'), findsNothing); + expect(find.textContaining('GitHub'), findsNothing); }); } + +class FakeBridgeStartupController extends BridgeStartupController { + FakeBridgeStartupController(this.result) + : super( + preferences: FakeAppPreferences(), + tokenStorage: FakeSecureTokenStorage(), + webSocketService: _NoopWebSocketService(), + ); + + final AppStartupResult result; + + @override + Future restore() async { + return result; + } +} + +class FakeAppPreferences extends AppPreferences { + FakeAppPreferences({this.bridgeUrl}); + + String? bridgeUrl; + + @override + String? getBridgeUrl() { + return bridgeUrl; + } + + @override + Future setBridgeUrl(String? url) async { + bridgeUrl = url; + } +} + +class FakeSecureTokenStorage extends SecureTokenStorage { + FakeSecureTokenStorage({this.token}) : super(const FlutterSecureStorage()); + + String? token; + + @override + Future getToken(String key) async { + return token; + } +} + +class _NoopWebSocketService extends WebSocketService {} diff --git a/apps/mobile/integration_test/chat_test.dart b/apps/mobile/integration_test/chat_test.dart index 73a9527..e6a7b11 100644 --- a/apps/mobile/integration_test/chat_test.dart +++ b/apps/mobile/integration_test/chat_test.dart @@ -1,19 +1,116 @@ +import 'dart:async'; + +import 'package:flutter/material.dart'; +import 'package:flutter_riverpod/flutter_riverpod.dart'; import 'package:flutter_test/flutter_test.dart'; -import 'package:patrol/patrol.dart'; +import 'package:go_router/go_router.dart'; +import 'package:integration_test/integration_test.dart'; +import 'package:recursor_mobile/core/network/connection_state.dart'; +import 'package:recursor_mobile/core/network/websocket_messages.dart'; +import 'package:recursor_mobile/core/network/websocket_service.dart'; +import 'package:recursor_mobile/core/providers/database_provider.dart'; +import 'package:recursor_mobile/core/providers/websocket_provider.dart'; +import 'package:recursor_mobile/core/storage/database.dart'; +import 'package:recursor_mobile/features/chat/presentation/screens/session_list_screen.dart'; void main() { - // Chat screen tests — require bridge connection - // These run against a real or mocked bridge server + IntegrationTestWidgetsFlutterBinding.ensureInitialized(); - patrolTest('Chat screen shows empty state without sessions', ($) async { - // TODO: mock bridge connection - // Verify empty state widget visible - expect(true, isTrue); // placeholder - }); + testWidgets('starting a chat session sends a session_start request', + (tester) async { + final database = AppDatabase.inMemory(); + final webSocketService = FakeIntegrationWebSocketService( + initialStatus: ConnectionStatus.connected, + ); + final router = GoRouter( + routes: [ + GoRoute( + path: '/', + builder: (_, __) => const SessionListScreen(), + ), + GoRoute( + path: '/home/chat/:sessionId', + builder: (_, state) => Scaffold( + body: Center( + child: Text('Chat ${state.pathParameters['sessionId']}'), + ), + ), + ), + ], + ); + + addTearDown(() async { + router.dispose(); + await webSocketService.close(); + await database.close(); + }); + + await tester.pumpWidget( + ProviderScope( + overrides: [ + databaseProvider.overrideWithValue(database), + webSocketServiceProvider.overrideWithValue(webSocketService), + ], + child: MaterialApp.router(routerConfig: router), + ), + ); + await tester.pumpAndSettle(); - patrolTest('Message input bar is visible and accepts text', ($) async { - // TODO: navigate to chat screen - // Verify input bar - expect(true, isTrue); // placeholder + await tester.tap(find.text('New Session')); + await tester.pumpAndSettle(); + await tester.enterText( + find.byKey(const Key('newSessionWorkingDirectoryField')), + '/workspace/integration-project', + ); + await tester.tap(find.text('Start Session')); + await tester.pumpAndSettle(); + + expect(webSocketService.sentMessages, hasLength(1)); + expect(webSocketService.sentMessages.single.type, + BridgeMessageType.sessionStart); + expect( + webSocketService.sentMessages.single.payload['working_directory'], + '/workspace/integration-project', + ); + expect(find.textContaining('Chat '), findsOneWidget); + + final sessions = await database.select(database.sessions).get(); + expect(sessions, hasLength(1)); + expect(sessions.single.workingDirectory, '/workspace/integration-project'); }); } + +class FakeIntegrationWebSocketService extends WebSocketService { + FakeIntegrationWebSocketService({required ConnectionStatus initialStatus}) + : _currentStatus = initialStatus; + + final StreamController _messageController = + StreamController.broadcast(); + final StreamController _statusController = + StreamController.broadcast(); + final List sentMessages = []; + final ConnectionStatus _currentStatus; + + @override + Stream get messages => _messageController.stream; + + @override + Stream get connectionStatus => _statusController.stream; + + @override + ConnectionStatus get currentStatus => _currentStatus; + + @override + bool send(BridgeMessage message) { + if (_currentStatus != ConnectionStatus.connected) { + return false; + } + sentMessages.add(message); + return true; + } + + Future close() async { + await _messageController.close(); + await _statusController.close(); + } +} diff --git a/apps/mobile/test/core/network/bridge_connection_validator_test.dart b/apps/mobile/test/core/network/bridge_connection_validator_test.dart new file mode 100644 index 0000000..b4418c6 --- /dev/null +++ b/apps/mobile/test/core/network/bridge_connection_validator_test.dart @@ -0,0 +1,102 @@ +import 'package:flutter_test/flutter_test.dart'; +import 'package:recursor_mobile/core/network/bridge_connection_validator.dart'; + +void main() { + group('BridgeConnectionValidator', () { + test('returns valid for proper wss URL and token', () { + final result = BridgeConnectionValidator.validate( + url: 'wss://device.tailnet.ts.net:3000', + token: 'valid-token-123', + ); + + expect(result.isValid, isTrue); + expect(result.errorMessage, isNull); + }); + + test('returns invalid when URL is empty', () { + final result = BridgeConnectionValidator.validate( + url: '', + token: 'token', + ); + + expect(result.isValid, isFalse); + expect(result.errorMessage, contains('Bridge URL is required')); + }); + + test('returns invalid when token is empty', () { + final result = BridgeConnectionValidator.validate( + url: 'wss://example.com', + token: '', + ); + + expect(result.isValid, isFalse); + expect(result.errorMessage, contains('token is required')); + }); + + test('returns invalid when URL has no scheme', () { + final result = BridgeConnectionValidator.validate( + url: 'device.tailnet.ts.net:3000', + token: 'token', + ); + + expect(result.isValid, isFalse); + expect(result.errorMessage, contains('valid bridge URL')); + }); + + test('returns invalid when URL uses http', () { + final result = BridgeConnectionValidator.validate( + url: 'http://device.tailnet.ts.net:3000', + token: 'token', + ); + + expect(result.isValid, isFalse); + expect(result.errorMessage, contains('wss://')); + }); + + test('returns invalid when URL uses ws (non-secure)', () { + final result = BridgeConnectionValidator.validate( + url: 'ws://device.tailnet.ts.net:3000', + token: 'token', + ); + + expect(result.isValid, isFalse); + expect(result.errorMessage, contains('must use wss://')); + }); + + test('trims whitespace from URL and token before validation', () { + final result = BridgeConnectionValidator.validate( + url: ' wss://device.tailnet.ts.net:3000 ', + token: ' token-with-spaces ', + ); + + expect(result.isValid, isTrue); + }); + + test('returns valid for localhost wss with port', () { + final result = BridgeConnectionValidator.validate( + url: 'wss://localhost:3000', + token: 'local-token', + ); + + expect(result.isValid, isTrue); + }); + + test('returns invalid for malformed URI', () { + final result = BridgeConnectionValidator.validate( + url: 'not a valid url', + token: 'token', + ); + + expect(result.isValid, isFalse); + }); + }); + + group('BridgeConnectionException', () { + test('stores and returns message', () { + const exception = BridgeConnectionException('Test error message'); + + expect(exception.message, 'Test error message'); + expect(exception.toString(), 'Test error message'); + }); + }); +} diff --git a/apps/mobile/test/core/network/websocket_service_test.dart b/apps/mobile/test/core/network/websocket_service_test.dart new file mode 100644 index 0000000..b828483 --- /dev/null +++ b/apps/mobile/test/core/network/websocket_service_test.dart @@ -0,0 +1,181 @@ +import 'dart:async'; +import 'dart:convert'; + +import 'package:flutter_test/flutter_test.dart'; +import 'package:recursor_mobile/core/network/bridge_connection_validator.dart'; +import 'package:recursor_mobile/core/network/connection_state.dart'; +import 'package:recursor_mobile/core/network/websocket_service.dart'; +import 'package:web_socket_channel/web_socket_channel.dart'; + +void main() { + group('WebSocketService', () { + test('sends auth and waits for connection_ack before becoming connected', + () async { + final fakeChannel = FakeWebSocketChannel(); + final service = WebSocketService(channelFactory: (_) => fakeChannel); + final statuses = []; + + final statusSub = service.connectionStatus.listen(statuses.add); + final Future connectFuture = service.connect( + url: 'wss://device.tailnet.ts.net:3000', + token: 'bridge-token-123', + ); + + await Future.delayed(Duration.zero); + + expect(statuses.first, ConnectionStatus.connecting); + expect(fakeChannel.sentMessages, hasLength(1)); + + final authFrame = + jsonDecode(fakeChannel.sentMessages.single) as Map; + expect(authFrame['type'], 'auth'); + expect( + (authFrame['payload'] as Map)['token'], + 'bridge-token-123', + ); + + fakeChannel.addIncoming( + jsonEncode({ + 'type': 'connection_ack', + 'timestamp': DateTime.now().toUtc().toIso8601String(), + 'payload': { + 'server_version': '1.0.0', + 'supported_agents': [], + 'active_sessions': >[], + }, + }), + ); + + await connectFuture; + + expect(service.currentStatus, ConnectionStatus.connected); + expect(statuses, contains(ConnectionStatus.connected)); + + await statusSub.cancel(); + service.dispose(); + await fakeChannel.close(); + }); + + test('surfaces connection_error without scheduling reconnects', () async { + final fakeChannel = FakeWebSocketChannel(); + var connectionAttempts = 0; + final service = WebSocketService(channelFactory: (_) { + connectionAttempts++; + return fakeChannel; + }); + + final Future connectFuture = service.connect( + url: 'wss://device.tailnet.ts.net:3000', + token: 'bridge-token-123', + ); + + await Future.delayed(Duration.zero); + + fakeChannel.addIncoming( + jsonEncode({ + 'type': 'connection_error', + 'timestamp': DateTime.now().toUtc().toIso8601String(), + 'payload': { + 'code': 'AUTH_FAILED', + 'message': 'Invalid or expired token', + }, + }), + ); + + await expectLater( + connectFuture, + throwsA( + isA().having( + (error) => error.message, + 'message', + 'Invalid or expired token', + ), + ), + ); + + await Future.delayed(const Duration(milliseconds: 100)); + + expect(service.currentStatus, ConnectionStatus.error); + expect(connectionAttempts, 1); + + service.dispose(); + await fakeChannel.close(); + }); + }); +} + +class FakeWebSocketChannel implements WebSocketChannel { + FakeWebSocketChannel({Future? ready}) + : ready = ready ?? Future.value(), + _incomingController = StreamController.broadcast(), + _sink = FakeWebSocketSink([]); + + final StreamController _incomingController; + final FakeWebSocketSink _sink; + + @override + final Future ready; + + List get sentMessages => _sink.messages; + + @override + int? get closeCode => null; + + @override + String? get closeReason => null; + + @override + String? get protocol => null; + + @override + Stream get stream => _incomingController.stream; + + @override + WebSocketSink get sink => _sink; + + void addIncoming(String message) { + _incomingController.add(message); + } + + Future close() async { + await _sink.close(); + await _incomingController.close(); + } + + @override + dynamic noSuchMethod(Invocation invocation) { + return super.noSuchMethod(invocation); + } +} + +class FakeWebSocketSink implements WebSocketSink { + FakeWebSocketSink(this.messages); + + final List messages; + final Completer _doneCompleter = Completer(); + + @override + Future get done => _doneCompleter.future; + + @override + void add(Object? data) { + messages.add(data as String); + } + + @override + void addError(Object error, [StackTrace? stackTrace]) {} + + @override + Future addStream(Stream stream) async { + await for (final data in stream) { + add(data); + } + } + + @override + Future close([int? closeCode, String? closeReason]) async { + if (!_doneCompleter.isCompleted) { + _doneCompleter.complete(); + } + } +} diff --git a/apps/mobile/test/core/sync/sync_queue_test.dart b/apps/mobile/test/core/sync/sync_queue_test.dart new file mode 100644 index 0000000..e44fb5a --- /dev/null +++ b/apps/mobile/test/core/sync/sync_queue_test.dart @@ -0,0 +1,179 @@ +import 'package:drift/drift.dart' show Value; +import 'package:flutter_test/flutter_test.dart'; +import 'package:recursor_mobile/core/network/connection_state.dart'; +import 'package:recursor_mobile/core/network/websocket_messages.dart'; +import 'package:recursor_mobile/core/network/websocket_service.dart'; +import 'package:recursor_mobile/core/storage/database.dart'; +import 'package:recursor_mobile/core/sync/sync_queue.dart'; + +void main() { + group('SyncQueueService', () { + late AppDatabase database; + late SyncQueueService service; + + setUp(() { + database = AppDatabase.inMemory(); + service = SyncQueueService(database: database); + }); + + tearDown(() async { + await database.close(); + }); + + test('keeps queued items pending when the bridge is unavailable', () async { + await service.enqueue( + 'message', + { + 'session_id': 'sess-1', + 'content': 'hello', + 'role': 'user', + }, + sessionId: 'sess-1', + ); + + final webSocket = FakeSyncWebSocketService( + status: ConnectionStatus.disconnected, + sendResult: false, + ); + + await service.flush(webSocket); + + final queuedItems = await database.select(database.syncQueue).get(); + final item = queuedItems.single; + + expect(item.synced, isFalse); + expect(item.retryCount, 1); + expect(item.lastError, 'Bridge unavailable'); + expect(webSocket.sentMessages, isEmpty); + }); + + test('replays queued message payloads using the bridge protocol', () async { + await service.enqueue( + 'message', + { + 'session_id': 'sess-1', + 'content': 'hello', + 'role': 'user', + }, + sessionId: 'sess-1', + ); + + final webSocket = FakeSyncWebSocketService( + status: ConnectionStatus.connected, + sendResult: true, + ); + + await service.flush(webSocket); + + final queuedItems = await database.select(database.syncQueue).get(); + final item = queuedItems.single; + + expect(item.synced, isTrue); + expect(item.retryCount, 0); + expect(webSocket.sentMessages, hasLength(1)); + expect(webSocket.sentMessages.single.type, BridgeMessageType.message); + expect(webSocket.sentMessages.single.payload['session_id'], 'sess-1'); + expect(webSocket.sentMessages.single.payload['content'], 'hello'); + expect(webSocket.sentMessages.single.payload['role'], 'user'); + }); + + test('marks local messages as synced after a successful flush', () async { + await database.sessionDao.upsertSession( + SessionsCompanion( + id: const Value('sess-1'), + agentType: const Value('claude-code'), + title: const Value('Queued Session'), + workingDirectory: const Value('/workspace/queued'), + status: const Value('active'), + createdAt: Value(DateTime.now().toUtc()), + updatedAt: Value(DateTime.now().toUtc()), + synced: const Value(true), + ), + ); + await database.messageDao.insertMessage( + MessagesCompanion( + id: const Value('msg-1'), + sessionId: const Value('sess-1'), + role: const Value('user'), + content: const Value('hello'), + messageType: const Value('text'), + createdAt: Value(DateTime.now().toUtc()), + updatedAt: Value(DateTime.now().toUtc()), + synced: const Value(false), + ), + ); + await service.enqueue( + 'message', + { + 'session_id': 'sess-1', + 'content': 'hello', + 'role': 'user', + 'local_message_id': 'msg-1', + }, + sessionId: 'sess-1', + ); + + final webSocket = FakeSyncWebSocketService( + status: ConnectionStatus.connected, + sendResult: true, + ); + + await service.flush(webSocket); + + final storedMessages = + await database.messageDao.getMessagesForSession('sess-1'); + expect(storedMessages.single.synced, isTrue); + }); + + test('replays queued session starts with the provided client session id', + () async { + await service.enqueue( + 'session_start', + { + 'agent': 'claude-code', + 'session_id': 'sess-queued', + 'working_directory': '/workspace/app', + 'resume': false, + }, + sessionId: 'sess-queued', + ); + + final webSocket = FakeSyncWebSocketService( + status: ConnectionStatus.connected, + sendResult: true, + ); + + await service.flush(webSocket); + + expect(webSocket.sentMessages, hasLength(1)); + expect( + webSocket.sentMessages.single.type, BridgeMessageType.sessionStart); + expect( + webSocket.sentMessages.single.payload['session_id'], 'sess-queued'); + expect( + webSocket.sentMessages.single.payload['working_directory'], + '/workspace/app', + ); + }); + }); +} + +class FakeSyncWebSocketService extends WebSocketService { + FakeSyncWebSocketService({ + required ConnectionStatus status, + required this.sendResult, + }) : _status = status; + + final ConnectionStatus _status; + final bool sendResult; + final List sentMessages = []; + + @override + ConnectionStatus get currentStatus => _status; + + @override + bool send(BridgeMessage message) { + sentMessages.add(message); + return sendResult; + } +} diff --git a/apps/mobile/test/features/chat/chat_provider_test.dart b/apps/mobile/test/features/chat/chat_provider_test.dart new file mode 100644 index 0000000..b8de9d4 --- /dev/null +++ b/apps/mobile/test/features/chat/chat_provider_test.dart @@ -0,0 +1,270 @@ +import 'dart:async'; + +import 'package:drift/drift.dart' show Value; +import 'package:flutter_riverpod/flutter_riverpod.dart'; +import 'package:flutter_test/flutter_test.dart'; +import 'package:recursor_mobile/core/network/connection_state.dart'; +import 'package:recursor_mobile/core/network/websocket_messages.dart'; +import 'package:recursor_mobile/core/network/websocket_service.dart'; +import 'package:recursor_mobile/core/providers/database_provider.dart'; +import 'package:recursor_mobile/core/providers/websocket_provider.dart'; +import 'package:recursor_mobile/core/storage/database.dart'; +import 'package:recursor_mobile/features/chat/domain/providers/chat_provider.dart'; + +void main() { + group('ChatNotifier', () { + late AppDatabase database; + late FakeChatWebSocketService webSocketService; + late ProviderContainer container; + late ProviderSubscription> chatNotifierSubscription; + + setUp(() async { + database = AppDatabase.inMemory(); + webSocketService = FakeChatWebSocketService( + initialStatus: ConnectionStatus.connected, + ); + container = ProviderContainer( + overrides: [ + databaseProvider.overrideWithValue(database), + webSocketServiceProvider.overrideWithValue(webSocketService), + ], + ); + chatNotifierSubscription = container.listen>( + chatNotifierProvider, + (_, __) {}, + fireImmediately: true, + ); + addTearDown(chatNotifierSubscription.close); + addTearDown(container.dispose); + await container.read(chatNotifierProvider.future); + }); + + tearDown(() async { + await webSocketService.close(); + await database.close(); + }); + + test('persists session readiness, tool events, and streamed responses', + () async { + webSocketService.emitMessage( + BridgeMessage( + type: BridgeMessageType.sessionReady, + timestamp: DateTime.now().toUtc(), + payload: { + 'session_id': 'sess-stream', + 'agent': 'claude-code', + 'working_directory': '/workspace/project-alpha', + 'status': 'ready', + 'model': 'claude-sonnet', + }, + ), + ); + webSocketService.emitMessage( + BridgeMessage( + type: BridgeMessageType.approvalRequired, + timestamp: DateTime.now().toUtc(), + payload: { + 'session_id': 'sess-stream', + 'tool_call_id': 'tool-1', + 'tool': 'edit_file', + 'params': {'path': 'lib/main.dart'}, + 'description': 'Approval required for edit_file', + 'risk_level': 'medium', + 'source': 'agent_sdk', + }, + ), + ); + webSocketService.emitMessage( + BridgeMessage( + type: BridgeMessageType.toolResult, + timestamp: DateTime.now().toUtc(), + payload: { + 'session_id': 'sess-stream', + 'tool_call_id': 'tool-1', + 'tool': 'edit_file', + 'result': { + 'success': true, + 'content': 'Updated lib/main.dart', + 'duration_ms': 18, + }, + }, + ), + ); + webSocketService.emitMessage( + BridgeMessage( + type: BridgeMessageType.streamStart, + timestamp: DateTime.now().toUtc(), + payload: { + 'session_id': 'sess-stream', + 'message_id': 'msg-1', + }, + ), + ); + webSocketService.emitMessage( + BridgeMessage( + type: BridgeMessageType.streamChunk, + timestamp: DateTime.now().toUtc(), + payload: { + 'session_id': 'sess-stream', + 'message_id': 'msg-1', + 'content': 'Hello', + }, + ), + ); + webSocketService.emitMessage( + BridgeMessage( + type: BridgeMessageType.streamChunk, + timestamp: DateTime.now().toUtc(), + payload: { + 'session_id': 'sess-stream', + 'message_id': 'msg-1', + 'content': ' world', + }, + ), + ); + webSocketService.emitMessage( + BridgeMessage( + type: BridgeMessageType.streamEnd, + timestamp: DateTime.now().toUtc(), + payload: { + 'session_id': 'sess-stream', + 'message_id': 'msg-1', + 'finish_reason': 'stop', + }, + ), + ); + + await _drainQueue(); + + final session = await database.sessionDao.getSession('sess-stream'); + final messages = + await database.messageDao.getMessagesForSession('sess-stream'); + + expect(session, isNotNull); + expect(session!.title, 'project-alpha'); + expect(messages, hasLength(3)); + expect( + messages.map((message) => message.messageType), + containsAll(['toolCall', 'toolResult', 'text']), + ); + expect( + messages.any((message) => message.content == 'Hello world'), + isTrue, + ); + }); + + test('queues outgoing messages offline and flushes them on reconnect', + () async { + await database.sessionDao.upsertSession( + SessionsCompanion( + id: const Value('sess-offline'), + agentType: const Value('claude-code'), + title: const Value('Offline Session'), + workingDirectory: const Value('/workspace/offline'), + status: const Value('active'), + createdAt: Value(DateTime.now().toUtc()), + updatedAt: Value(DateTime.now().toUtc()), + synced: const Value(true), + ), + ); + + webSocketService.currentStatusValue = ConnectionStatus.disconnected; + + await container + .read(chatNotifierProvider.notifier) + .sendMessage('sess-offline', 'Queued hello'); + await _drainQueue(); + + var queuedItems = await database.select(database.syncQueue).get(); + var storedMessages = + await database.messageDao.getMessagesForSession('sess-offline'); + + expect(queuedItems, hasLength(1)); + expect(queuedItems.single.operation, 'message'); + expect(queuedItems.single.synced, isFalse); + expect(storedMessages.single.synced, isFalse); + expect(webSocketService.sentMessages, isEmpty); + + webSocketService.currentStatusValue = ConnectionStatus.connected; + webSocketService.emitStatus(ConnectionStatus.connected); + await _drainQueue(); + + queuedItems = await database.select(database.syncQueue).get(); + storedMessages = + await database.messageDao.getMessagesForSession('sess-offline'); + + expect(queuedItems.single.synced, isTrue); + expect(storedMessages.single.synced, isTrue); + expect(webSocketService.sentMessages, hasLength(1)); + expect( + webSocketService.sentMessages.single.type, BridgeMessageType.message); + expect( + webSocketService.sentMessages.single.payload['content'], + 'Queued hello', + ); + }); + }); +} + +Future _drainQueue() async { + await Future.delayed(Duration.zero); + await Future.delayed(const Duration(milliseconds: 20)); +} + +class FakeChatWebSocketService extends WebSocketService { + FakeChatWebSocketService({required ConnectionStatus initialStatus}) + : _currentStatus = initialStatus; + + final StreamController _messageController = + StreamController.broadcast(); + final StreamController _statusController = + StreamController.broadcast(); + final List sentMessages = []; + + ConnectionStatus _currentStatus; + Map? _lastConnectionAckPayload; + bool sendResult = true; + + set currentStatusValue(ConnectionStatus value) { + _currentStatus = value; + } + + @override + Stream get messages => _messageController.stream; + + @override + Stream get connectionStatus => _statusController.stream; + + @override + ConnectionStatus get currentStatus => _currentStatus; + + @override + Map? get lastConnectionAckPayload => + _lastConnectionAckPayload; + + @override + bool send(BridgeMessage message) { + if (_currentStatus != ConnectionStatus.connected) { + return false; + } + sentMessages.add(message); + return sendResult; + } + + void emitMessage(BridgeMessage message) { + if (message.type == BridgeMessageType.connectionAck) { + _lastConnectionAckPayload = message.payload; + } + _messageController.add(message); + } + + void emitStatus(ConnectionStatus status) { + _currentStatus = status; + _statusController.add(status); + } + + Future close() async { + await _messageController.close(); + await _statusController.close(); + } +} diff --git a/apps/mobile/test/features/chat/tool_card_test.dart b/apps/mobile/test/features/chat/tool_card_test.dart new file mode 100644 index 0000000..3e81747 --- /dev/null +++ b/apps/mobile/test/features/chat/tool_card_test.dart @@ -0,0 +1,218 @@ +import 'package:flutter/material.dart'; +import 'package:flutter_test/flutter_test.dart'; +import 'package:recursor_mobile/core/models/message_models.dart'; +import 'package:recursor_mobile/features/chat/presentation/widgets/tool_card.dart'; + +void main() { + group('ToolCard', () { + testWidgets('shows running state without metadata', (tester) async { + await tester.pumpWidget( + const MaterialApp( + home: Scaffold( + body: ToolCard( + toolName: 'edit_file', + params: {'path': 'lib/main.dart'}, + id: 'tool-1', + isCompleted: false, + ), + ), + ), + ); + + expect(find.text('edit_file'), findsOneWidget); + expect(find.byIcon(Icons.hourglass_empty), findsOneWidget); + }); + + testWidgets('shows approval required state with risk level badge', + (tester) async { + await tester.pumpWidget( + const MaterialApp( + home: Scaffold( + body: ToolCard( + toolName: 'edit_file', + params: {'path': 'lib/main.dart'}, + id: 'tool-1', + isCompleted: false, + metadata: { + 'risk_level': 'high', + 'source': 'agent_sdk', + }, + ), + ), + ), + ); + + expect(find.text('edit_file'), findsOneWidget); + // High risk badge should be visible + expect(find.text('HIGH'), findsOneWidget); + // Approvals banner should be visible + expect(find.textContaining('Approval required'), findsOneWidget); + // Pending icon appears twice (in header and banner) + expect(find.byIcon(Icons.pending_actions), findsNWidgets(2)); + }); + + testWidgets('shows completed state with result', (tester) async { + await tester.pumpWidget( + const MaterialApp( + home: Scaffold( + body: ToolCard( + toolName: 'edit_file', + params: {'path': 'lib/main.dart'}, + id: 'tool-1', + isCompleted: true, + result: ToolResult( + success: true, + content: 'File updated successfully', + durationMs: 150, + ), + ), + ), + ), + ); + + expect(find.text('edit_file'), findsOneWidget); + expect(find.byIcon(Icons.check_circle), findsOneWidget); + }); + + testWidgets('shows failed state with error', (tester) async { + await tester.pumpWidget( + const MaterialApp( + home: Scaffold( + body: ToolCard( + toolName: 'edit_file', + params: {'path': 'lib/main.dart'}, + id: 'tool-1', + isCompleted: true, + result: ToolResult( + success: false, + content: '', + error: 'Permission denied', + durationMs: 50, + ), + ), + ), + ), + ); + + expect(find.text('edit_file'), findsOneWidget); + expect(find.byIcon(Icons.error), findsOneWidget); + }); + + testWidgets('shows medium risk level badge', (tester) async { + await tester.pumpWidget( + const MaterialApp( + home: Scaffold( + body: ToolCard( + toolName: 'bash', + params: {'command': 'ls -la'}, + id: 'tool-2', + isCompleted: false, + metadata: {'risk_level': 'medium'}, + ), + ), + ), + ); + + expect(find.text('MEDIUM'), findsOneWidget); + }); + + testWidgets('shows critical risk level badge', (tester) async { + await tester.pumpWidget( + const MaterialApp( + home: Scaffold( + body: ToolCard( + toolName: 'bash', + params: {'command': 'rm -rf /'}, + id: 'tool-3', + isCompleted: false, + metadata: {'risk_level': 'critical'}, + ), + ), + ), + ); + + expect(find.text('CRITICAL'), findsOneWidget); + }); + + testWidgets('expands parameters on tap', (tester) async { + await tester.pumpWidget( + const MaterialApp( + home: Scaffold( + body: ToolCard( + toolName: 'edit_file', + params: { + 'path': 'lib/main.dart', + 'new_content': 'void main() {}' + }, + id: 'tool-1', + isCompleted: false, + ), + ), + ), + ); + + // Parameters section should be present + expect(find.text('Parameters'), findsOneWidget); + + // Tap on Parameters section + await tester.tap(find.text('Parameters')); + await tester.pumpAndSettle(); + + // Key value list should now be visible (check for the widget type) + expect(find.byType(ToolCard), findsOneWidget); + }); + + group('tool icon selection', () { + testWidgets('shows file icon for file operations', (tester) async { + await tester.pumpWidget( + const MaterialApp( + home: Scaffold( + body: ToolCard( + toolName: 'read_file', + params: {}, + id: 'tool-1', + isCompleted: false, + ), + ), + ), + ); + + expect(find.byType(ToolCard), findsOneWidget); + }); + + testWidgets('shows terminal icon for bash operations', (tester) async { + await tester.pumpWidget( + const MaterialApp( + home: Scaffold( + body: ToolCard( + toolName: 'bash', + params: {}, + id: 'tool-1', + isCompleted: false, + ), + ), + ), + ); + + expect(find.byType(ToolCard), findsOneWidget); + }); + + testWidgets('shows git icon for git operations', (tester) async { + await tester.pumpWidget( + const MaterialApp( + home: Scaffold( + body: ToolCard( + toolName: 'git_status', + params: {}, + id: 'tool-1', + isCompleted: false, + ), + ), + ), + ); + + expect(find.byType(ToolCard), findsOneWidget); + }); + }); + }); +} diff --git a/apps/mobile/test/features/startup/bridge_startup_controller_test.dart b/apps/mobile/test/features/startup/bridge_startup_controller_test.dart new file mode 100644 index 0000000..fa4a5bd --- /dev/null +++ b/apps/mobile/test/features/startup/bridge_startup_controller_test.dart @@ -0,0 +1,144 @@ +import 'package:flutter_secure_storage/flutter_secure_storage.dart'; +import 'package:flutter_test/flutter_test.dart'; +import 'package:recursor_mobile/core/network/bridge_connection_validator.dart'; +import 'package:recursor_mobile/core/network/connection_state.dart'; +import 'package:recursor_mobile/core/network/websocket_service.dart'; +import 'package:recursor_mobile/core/storage/preferences.dart'; +import 'package:recursor_mobile/core/storage/secure_token_storage.dart'; +import 'package:recursor_mobile/features/startup/domain/bridge_startup_controller.dart'; + +void main() { + group('BridgeStartupController', () { + test('returns bridge setup when no saved pairing exists', () async { + final controller = BridgeStartupController( + preferences: FakeAppPreferences(), + tokenStorage: FakeSecureTokenStorage(), + webSocketService: FakeStartupWebSocketService(), + ); + + final result = await controller.restore(); + + expect(result.destination, AppStartupDestination.bridgeSetup); + expect(result.message, isNull); + }); + + test('returns bridge setup with validation error when URL is invalid', + () async { + final controller = BridgeStartupController( + preferences: FakeAppPreferences(bridgeUrl: 'http://invalid.com'), + tokenStorage: FakeSecureTokenStorage(token: 'token-123'), + webSocketService: FakeStartupWebSocketService(), + ); + + final result = await controller.restore(); + + expect(result.destination, AppStartupDestination.bridgeSetup); + expect(result.message, contains('Invalid saved bridge configuration')); + }); + + test('returns bridge setup with validation error when URL is not wss', + () async { + final controller = BridgeStartupController( + preferences: FakeAppPreferences(bridgeUrl: 'ws://device.ts.net:3000'), + tokenStorage: FakeSecureTokenStorage(token: 'token-123'), + webSocketService: FakeStartupWebSocketService(), + ); + + final result = await controller.restore(); + + expect(result.destination, AppStartupDestination.bridgeSetup); + expect(result.message, contains('must use wss://')); + }); + + test('restores the saved bridge pairing and opens the home shell', + () async { + final service = FakeStartupWebSocketService(); + final controller = BridgeStartupController( + preferences: FakeAppPreferences( + bridgeUrl: 'wss://device.tailnet.ts.net:3000', + ), + tokenStorage: FakeSecureTokenStorage(token: 'bridge-token-123'), + webSocketService: service, + ); + + final result = await controller.restore(); + + expect(result.destination, AppStartupDestination.home); + expect(service.lastUrl, 'wss://device.tailnet.ts.net:3000'); + expect(service.lastToken, 'bridge-token-123'); + expect(service.currentStatus, ConnectionStatus.connected); + }); + + test('falls back to bridge setup when reconnecting fails', () async { + final controller = BridgeStartupController( + preferences: FakeAppPreferences( + bridgeUrl: 'wss://device.tailnet.ts.net:3000', + ), + tokenStorage: FakeSecureTokenStorage(token: 'bridge-token-123'), + webSocketService: FakeStartupWebSocketService( + error: const BridgeConnectionException('Invalid token'), + ), + ); + + final result = await controller.restore(); + + expect(result.destination, AppStartupDestination.bridgeSetup); + expect(result.message, contains('Unable to reconnect')); + expect(result.message, contains('Invalid token')); + }); + }); +} + +class FakeAppPreferences extends AppPreferences { + FakeAppPreferences({this.bridgeUrl}); + + String? bridgeUrl; + + @override + String? getBridgeUrl() { + return bridgeUrl; + } + + @override + Future setBridgeUrl(String? url) async { + bridgeUrl = url; + } +} + +class FakeSecureTokenStorage extends SecureTokenStorage { + FakeSecureTokenStorage({this.token}) : super(const FlutterSecureStorage()); + + String? token; + + @override + Future getToken(String key) async { + return token; + } + + @override + Future saveToken(String key, String value) async { + token = value; + } +} + +class FakeStartupWebSocketService extends WebSocketService { + FakeStartupWebSocketService({this.error}); + + final Object? error; + String? lastUrl; + String? lastToken; + ConnectionStatus _currentStatus = ConnectionStatus.disconnected; + + @override + ConnectionStatus get currentStatus => _currentStatus; + + @override + Future connect({required String url, required String token}) async { + lastUrl = url; + lastToken = token; + if (error != null) { + throw error!; + } + _currentStatus = ConnectionStatus.connected; + } +} diff --git a/apps/mobile/test/router_test.dart b/apps/mobile/test/router_test.dart new file mode 100644 index 0000000..4159b27 --- /dev/null +++ b/apps/mobile/test/router_test.dart @@ -0,0 +1,59 @@ +// Router integration smoke test — verifies key feature screen imports resolve. +// Run with: flutter test test/router_test.dart + +import 'package:flutter_test/flutter_test.dart'; +import 'package:recursor_mobile/features/agents/presentation/screens/agent_list_screen.dart'; +import 'package:recursor_mobile/features/approvals/presentation/screens/approval_detail_screen.dart'; +import 'package:recursor_mobile/features/approvals/presentation/screens/approvals_screen.dart'; +import 'package:recursor_mobile/features/git/presentation/screens/git_screen.dart'; +import 'package:recursor_mobile/features/settings/presentation/screens/settings_screen.dart'; +import 'package:recursor_mobile/features/startup/presentation/screens/bridge_setup_screen.dart'; +import 'package:recursor_mobile/features/startup/presentation/screens/splash_screen.dart'; +import 'package:recursor_mobile/features/terminal/presentation/screens/terminal_screen.dart'; + +void main() { + group('Feature Screen Reachability', () { + test('SplashScreen exists and instantiates', () { + const screen = SplashScreen(); + expect(screen, isA()); + }); + + test('BridgeSetupScreen exists and instantiates', () { + const screen = BridgeSetupScreen(); + expect(screen, isA()); + }); + + test('AgentListScreen exists and instantiates', () { + const screen = AgentListScreen(); + expect(screen, isA()); + }); + + test('ApprovalDetailScreen exists and instantiates', () { + const screen = ApprovalDetailScreen(toolCallId: 'test-id'); + expect(screen, isA()); + }); + + test('ApprovalsScreen exists and instantiates', () { + const screen = ApprovalsScreen(); + expect(screen, isA()); + }); + + test('GitScreen exists and instantiates', () { + const screen = GitScreen(sessionId: ''); + expect(screen, isA()); + }); + + test('SettingsScreen exists and instantiates', () { + const screen = SettingsScreen(); + expect(screen, isA()); + }); + + test('TerminalScreen exists and instantiates', () { + const screen = TerminalScreen( + sessionId: 'test-session', + workingDirectory: '~/test', + ); + expect(screen, isA()); + }); + }); +} diff --git a/apps/mobile/test/widget_test.dart b/apps/mobile/test/widget_test.dart index f0bf8e2..dd3f8d7 100644 --- a/apps/mobile/test/widget_test.dart +++ b/apps/mobile/test/widget_test.dart @@ -1,19 +1,83 @@ +import 'dart:async'; + import 'package:flutter/material.dart'; +import 'package:flutter_riverpod/flutter_riverpod.dart'; import 'package:flutter_test/flutter_test.dart'; +import 'package:recursor_mobile/core/network/connection_state.dart'; +import 'package:recursor_mobile/core/network/websocket_messages.dart'; +import 'package:recursor_mobile/core/network/websocket_service.dart'; +import 'package:recursor_mobile/core/providers/websocket_provider.dart'; +import 'package:recursor_mobile/features/chat/presentation/widgets/chat_input_bar.dart'; void main() { - testWidgets('renders ReCursor placeholder shell', - (WidgetTester tester) async { + testWidgets('offline chat input queues locally instead of blocking send', + (tester) async { + final webSocketService = FakeWidgetWebSocketService( + initialStatus: ConnectionStatus.disconnected, + ); + String? submittedText; + + addTearDown(webSocketService.close); + await tester.pumpWidget( - const MaterialApp( - home: Scaffold( - body: Center( - child: Text('ReCursor'), + ProviderScope( + overrides: [ + webSocketServiceProvider.overrideWithValue(webSocketService), + ], + child: MaterialApp( + home: Scaffold( + body: ChatInputBar( + sessionId: 'sess-widget', + onSend: (text) => submittedText = text, + onVoice: () {}, + ), ), ), ), ); + await tester.pump(); - expect(find.text('ReCursor'), findsOneWidget); + expect( + find.text('Offline — messages will send when reconnected'), + findsOneWidget, + ); + expect(find.byIcon(Icons.schedule_send), findsOneWidget); + + await tester.enterText(find.byType(TextField), 'Queue me'); + await tester.pump(); + await tester.tap(find.byIcon(Icons.schedule_send)); + await tester.pump(); + + expect(submittedText, 'Queue me'); }); } + +class FakeWidgetWebSocketService extends WebSocketService { + FakeWidgetWebSocketService({required ConnectionStatus initialStatus}) + : _currentStatus = initialStatus; + + final StreamController _messageController = + StreamController.broadcast(); + final StreamController _statusController = + StreamController.broadcast(); + final ConnectionStatus _currentStatus; + + @override + Stream get messages => _messageController.stream; + + @override + Stream get connectionStatus => _statusController.stream; + + @override + ConnectionStatus get currentStatus => _currentStatus; + + @override + bool send(BridgeMessage message) { + return _currentStatus == ConnectionStatus.connected; + } + + Future close() async { + await _messageController.close(); + await _statusController.close(); + } +} From db5cef1287692868b0828109c574046777b435e0 Mon Sep 17 00:00:00 2001 From: MasuRii Date: Fri, 20 Mar 2026 12:58:18 +0800 Subject: [PATCH 21/22] docs: update architecture and wireframes for startup flow Update documentation to reflect auth removal and startup flow. Enhance bridge protocol documentation with new message types. Update wireframes for all screens with improved layouts. Revise project structure and testing strategy documents. - Replace 01-auth.md wireframe with 01-startup.md - Update PLAN.md and README.md with current architecture - Enhance bridge-protocol.md with extended protocol - Update security-architecture.md with new auth model - Refresh all wireframe documents with current UI design --- docs/PLAN.md | 34 ++++++++------- docs/README.md | 6 ++- docs/architecture/overview.md | 14 +++---- docs/bridge-protocol.md | 48 ++++++++++----------- docs/data-models.md | 14 +++---- docs/idea.md | 18 ++++---- docs/integration/agent-sdk.md | 4 +- docs/integration/claude-code-hooks.md | 6 +-- docs/legal/privacy-policy.md | 11 +++-- docs/project-structure.md | 29 +++++-------- docs/push-notifications.md | 4 +- docs/research.md | 2 + docs/security-architecture.md | 32 +++++++------- docs/testing-strategy.md | 8 ++-- docs/wireframes/03-chat.md | 34 +++++++-------- docs/wireframes/04-repos.md | 16 +++---- docs/wireframes/05-git.md | 22 +++++----- docs/wireframes/06-diff.md | 40 +++++++++--------- docs/wireframes/07-approvals.md | 34 +++++++-------- docs/wireframes/08-terminal.md | 4 +- docs/wireframes/09-agents.md | 2 +- docs/wireframes/10-settings.md | 27 +++++------- docs/wireframes/11-tablet.md | 60 +++++++++++++-------------- docs/wireframes/README.md | 23 ++++++---- 24 files changed, 245 insertions(+), 247 deletions(-) diff --git a/docs/PLAN.md b/docs/PLAN.md index a3dbecc..70544ba 100644 --- a/docs/PLAN.md +++ b/docs/PLAN.md @@ -1,6 +1,6 @@ # ReCursor — Implementation Plan -> **Flutter mobile app** providing OpenCode-like UI/UX for AI coding agents, with events sourced from Claude Code via supported integration mechanisms. +> **Flutter mobile app** providing OpenCode-like UI/UX for AI coding agents. Bridge-first, no-login: connects to your user-controlled desktop bridge. --- @@ -42,16 +42,24 @@ flowchart TB > ⚠️ **Claude Code Remote Control is first-party only** — there is no public API for third-party clients to join or mirror existing Claude Code sessions. -**Supported Integration Path:** +**Supported Integration Paths:** - **Claude Code Hooks** — HTTP-based event observation (one-way) - **Agent SDK** — Parallel agent sessions (not mirroring) - **MCP (Model Context Protocol)** — Tool interoperability +### Bridge-First, No-Login Workflow + +ReCursor uses a **bridge-first** connection model with no user accounts: +- **No sign-in required** — the app opens to bridge pairing/restore, not a login screen +- **User-controlled bridge** — the bridge runs on your development machine, not a hosted service +- **Secure device pairing** — QR code pairing with device tokens stored in secure storage +- **Remote access** — optional secure tunneling (Tailscale, WireGuard) to your own bridge + --- ## Phase 1: Foundation -**Goal:** Bootable app with auth, secure connectivity to bridge, and basic agent chat with OpenCode-style UI. +**Goal:** Bootable app with direct bridge connectivity (no auth flow) and basic agent chat with OpenCode-style UI. ### 1.1 Project Scaffolding & CI/CD - [ ] Initialize Flutter project (iOS + Android targets) @@ -61,21 +69,15 @@ flowchart TB - [ ] Configure Fastlane for iOS (Match) and Android (keystore) - [ ] **Tests:** Verify project builds on both platforms -### 1.2 Authentication -- [ ] Implement GitHub OAuth2 flow -- [ ] Support Personal Access Token (PAT) auth as fallback -- [ ] Secure token storage via `flutter_secure_storage` -- [ ] Auth state management with Riverpod -- [ ] **Tests:** Unit test auth provider state transitions - -### 1.3 Bridge Connection & Security +### 1.2 Bridge Connection & Security (First Screen) - [ ] Define WebSocket protocol (see [bridge-protocol.md](bridge-protocol.md)) - [ ] Implement WebSocket client service with `web_socket_channel` -- [ ] Connection pairing via QR code (encode bridge URL + auth token) +- [ ] Connection pairing via QR code (encode bridge URL + device pairing token) +- [ ] Restore saved bridge pairings on startup before entering the main shell - [ ] Tailscale integration documentation / setup guide - [ ] Always use `wss://`; optional certificate pinning - [ ] Auto-reconnect with exponential backoff -- [ ] **Tests:** Unit test WebSocket service with mocks +- [ ] **Tests:** Unit test WebSocket service with mocks and startup restore logic ### 1.4 Basic Agent Chat Interface (OpenCode-style) - [ ] Chat UI with message list (user messages + agent responses) @@ -91,7 +93,7 @@ flowchart TB - [ ] File viewer with syntax highlighting - [ ] **Tests:** Unit test bridge file commands -**Phase 1 Deliverable:** App authenticates via GitHub, connects to bridge, sends messages to Agent SDK session, displays streamed responses with OpenCode-style UI. +**Phase 1 Deliverable:** App connects directly to bridge (no auth flow), sends messages to Agent SDK session, displays streamed responses with OpenCode-style UI. --- @@ -224,7 +226,7 @@ flowchart TB | **Unit** | `flutter_test` + `mockito` | Services, providers, models, serialization | | **Widget** | `flutter_test` | UI components with mock dependencies | | **Golden** | `alchemist` | Visual regression for key screens | -| **Integration** | `integration_test` | Full flows: auth → connect → chat → hooks | +| **Integration** | `integration_test` | Full flows: connect → chat → hooks | | **E2E** | `patrol` | Complete user journeys on real devices | --- @@ -236,7 +238,7 @@ flowchart TB | Framework | Flutter | Cross-platform, CC Pocket precedent | | State | Riverpod | Type-safe, testable, Conduit pattern | | Networking | `web_socket_channel` | Standard Flutter WebSocket | -| Auth | GitHub OAuth2 + PAT | `github_oauth` package | +| UI State | Riverpod | Type-safe state management | | Local DB | Drift (SQLite) | Type-safe queries, migrations | | Cache | Hive | Fast key-value for ephemeral data | | Notifications | `flutter_local_notifications` | Local alerts when backgrounded | diff --git a/docs/README.md b/docs/README.md index cfb4560..e478a4e 100644 --- a/docs/README.md +++ b/docs/README.md @@ -1,6 +1,6 @@ # ReCursor Documentation -> **ReCursor** — A Flutter mobile app providing OpenCode-like UI/UX for AI coding agents, with events sourced from Claude Code via supported integration mechanisms (Hooks/Agent SDK). +> **ReCursor** — A Flutter mobile app providing OpenCode-like UI/UX for AI coding agents. Bridge-first, no-login workflow: connects to your user-controlled desktop bridge via secure tunnel. --- @@ -101,10 +101,12 @@ flowchart TB > ⚠️ **Claude Code Remote Control Protocol**: The Remote Control feature is designed exclusively for first-party Anthropic clients. There is no public API for third-party clients to join or mirror existing Claude Code sessions. > -> **Supported Integration Path:** +> **Supported Integration Paths:** > - **Claude Code Hooks** — HTTP-based event observation (one-way) > - **Agent SDK** — Parallel agent sessions (not mirroring) > - **MCP (Model Context Protocol)** — Tool interoperability +> +> **Bridge-First Workflow:** ReCursor uses a bridge-first, no-login model. The mobile app connects directly to a user-controlled desktop bridge. No hosted accounts, no sign-in required — just secure device pairing via QR code and optional tunneling for remote access. --- diff --git a/docs/architecture/overview.md b/docs/architecture/overview.md index 7d33a6e..9f5da96 100644 --- a/docs/architecture/overview.md +++ b/docs/architecture/overview.md @@ -1,6 +1,6 @@ # Architecture Overview -> System architecture for ReCursor: a Flutter mobile app with OpenCode-like UI consuming Claude Code events via supported integration mechanisms. +> System architecture for ReCursor: a Flutter mobile app with OpenCode-like UI. Bridge-first, no-login: connects to your user-controlled desktop bridge via secure tunnel. --- @@ -46,12 +46,12 @@ flowchart TB | Approach | Status | Notes | |----------|--------|-------| -| Direct Remote Control Protocol | ❌ Not Available | First-party only (claude.ai/code, official apps) | +| Direct Remote Control Protocol | ❌ Not Available | First-party only (claude.ai/code, official apps). No public API for third-party clients. | | **Claude Code Hooks** | ✅ Supported | HTTP-based event observation (one-way) | -| **Agent SDK** | ✅ Supported | Parallel agent sessions | +| **Agent SDK** | ✅ Supported | Parallel agent sessions (not mirroring) | | MCP (Model Context Protocol) | ✅ Supported | Tool interoperability | -**Selected Architecture:** Hybrid approach using Hooks for event observation + Agent SDK for parallel sessions. +**Selected Architecture:** Hybrid approach using Hooks for event observation + Agent SDK for parallel sessions. ReCursor does not claim to mirror or control existing Claude Code sessions. ### 2. UI/UX Pattern @@ -114,7 +114,7 @@ flowchart LR subgraph Network["Network Layers"] WireGuard["WireGuard/Tailscale\n(Network Layer)"] TLS["TLS 1.3\n(Transport Layer)"] - Auth["Token Auth\n(Application Layer)"] + Auth["Device Pairing Token\n(Application Layer)"] end Phone["📱 Mobile"] --> WireGuard @@ -123,9 +123,9 @@ flowchart LR Auth --> Bridge["Bridge Server"] ``` -1. **Network Layer**: Tailscale/WireGuard mesh VPN +1. **Network Layer**: Tailscale/WireGuard mesh VPN (or your preferred secure tunnel) 2. **Transport Layer**: WSS (WebSocket Secure) with TLS 1.3 -3. **Application Layer**: Token-based authentication on WebSocket handshake +3. **Application Layer**: Device pairing token on WebSocket handshake (no user accounts, no login) --- diff --git a/docs/bridge-protocol.md b/docs/bridge-protocol.md index 1a0dbf5..454ab39 100644 --- a/docs/bridge-protocol.md +++ b/docs/bridge-protocol.md @@ -1,6 +1,6 @@ # Bridge Protocol Specification -> WebSocket message protocol between the ReCursor Flutter mobile app and the TypeScript bridge server. +> WebSocket message protocol between the ReCursor Flutter mobile app and the user-controlled TypeScript bridge server. Bridge-first, no-login: device pairing via QR code, no user accounts. --- @@ -50,14 +50,14 @@ All messages are JSON objects with a `type` field and an optional `id` for reque ### Connection #### `auth` (client -> server) -Sent immediately after WebSocket connection opens. +Sent immediately after WebSocket connection opens for device pairing authentication. ```json { "type": "auth", "id": "auth-001", "payload": { - "token": "bridge-auth-token-xxxxx", + "token": "device-pairing-token-xxxxx", "client_version": "1.0.0", "platform": "ios" } @@ -75,7 +75,7 @@ Confirms authentication and connection. "server_version": "1.0.0", "supported_agents": ["claude-code", "opencode", "aider", "goose"], "active_sessions": [ - { "session_id": "sess-abc", "agent": "claude-code", "title": "Fix auth bug" } + { "session_id": "sess-abc", "agent": "claude-code", "title": "Bridge startup validation" } ] } } @@ -170,7 +170,7 @@ Send a chat message to the agent. "id": "msg-001", "payload": { "session_id": "sess-abc123", - "content": "Fix the auth bug in login.dart", + "content": "Tighten the bridge startup validation in bridge_setup_screen.dart", "role": "user" } } @@ -198,7 +198,7 @@ Chunk of streamed response content. "payload": { "session_id": "sess-abc123", "message_id": "msg-resp-001", - "content": "I'll help you fix the auth bug", + "content": "I'll tighten the bridge startup validation", "is_tool_use": false } } @@ -234,11 +234,11 @@ Agent wants to use a tool. Sent when Agent SDK initiates tool use. "tool_call_id": "call-abc123", "tool": "edit_file", "params": { - "file_path": "/home/user/project/lib/auth.dart", - "old_string": "void login() {", - "new_string": "void login() async {" + "file_path": "/home/user/project/lib/features/startup/bridge_setup_screen.dart", + "old_string": "return wsAllowed(url);", + "new_string": "return requireWss(url);" }, - "description": "Add async keyword to login function" + "description": "Require secure bridge URLs during startup" } } ``` @@ -343,12 +343,12 @@ Current git status. "id": "git-001", "payload": { "session_id": "sess-abc123", - "branch": "feature/auth-fix", + "branch": "feature/bridge-startup", "ahead": 2, "behind": 0, "is_clean": false, "changes": [ - { "path": "lib/auth.dart", "status": "modified", "additions": 5, "deletions": 2 } + { "path": "lib/features/startup/bridge_setup_screen.dart", "status": "modified", "additions": 5, "deletions": 2 } ] } } @@ -363,8 +363,8 @@ Create a commit. "id": "git-002", "payload": { "session_id": "sess-abc123", - "message": "Fix auth bug in login flow", - "files": ["lib/auth.dart"] // null = all staged + "message": "Tighten bridge startup validation", + "files": ["lib/features/startup/bridge_setup_screen.dart"] // null = all staged } } ``` @@ -378,7 +378,7 @@ Request diff for files. "id": "git-003", "payload": { "session_id": "sess-abc123", - "files": ["lib/auth.dart"], // null = all changes + "files": ["lib/features/startup/bridge_setup_screen.dart"], // null = all changes "cached": false } } @@ -395,9 +395,9 @@ Diff content. "session_id": "sess-abc123", "files": [ { - "path": "lib/auth.dart", - "old_path": "lib/auth.dart", - "new_path": "lib/auth.dart", + "path": "lib/features/startup/bridge_setup_screen.dart", + "old_path": "lib/features/startup/bridge_setup_screen.dart", + "new_path": "lib/features/startup/bridge_setup_screen.dart", "status": "modified", "additions": 5, "deletions": 2, @@ -409,9 +409,9 @@ Diff content. "new_start": 10, "new_lines": 5, "lines": [ - { "type": "context", "content": " class AuthService {" }, - { "type": "removed", "content": "- void login() {" }, - { "type": "added", "content": "+ void login() async {" }, + { "type": "context", "content": " class BridgeConnectionValidator {" }, + { "type": "removed", "content": "- return wsAllowed(url);" }, + { "type": "added", "content": "+ return requireWss(url);" }, { "type": "context", "content": " // ..." } ] } @@ -467,7 +467,7 @@ Read file content. "id": "file-002", "payload": { "session_id": "sess-abc123", - "path": "/home/user/project/lib/auth.dart", + "path": "/home/user/project/lib/features/startup/bridge_setup_screen.dart", "offset": 0, "limit": 100 } @@ -505,8 +505,8 @@ Server-initiated notification. "payload": { "session_id": "sess-abc123", "notification_type": "approval_required", - "title": "Approval needed: Edit login.dart", - "body": "Claude Code wants to change the OAuth callback URL.", + "title": "Approval needed: Update bridge_setup_screen.dart", + "body": "Claude Code wants to tighten bridge URL validation before pairing.", "priority": "high", "data": { "tool_call_id": "tool-001", diff --git a/docs/data-models.md b/docs/data-models.md index 4535ccd..124a681 100644 --- a/docs/data-models.md +++ b/docs/data-models.md @@ -61,7 +61,7 @@ class Agents extends Table { TextColumn get displayName => text()(); // "Claude Code" TextColumn get agentType => text()(); // "claude-code", "opencode", "aider", "goose", "custom" TextColumn get bridgeUrl => text()(); // "wss://100.78.42.15:3000" - TextColumn get authToken => text()(); // Encrypted bridge auth token + TextColumn get authToken => text()(); // Encrypted bridge pairing token (device-bridge auth, not user account) TextColumn get workingDirectory => text().nullable()(); TextColumn get status => text() .withDefault(const Constant('disconnected'))(); // "connected", "disconnected", "inactive" @@ -138,22 +138,22 @@ class TerminalSessions extends Table { ## Hive Boxes (Key-Value) -### Auth Box +### Connection Box ```dart @HiveType(typeId: 1) -class AuthState { +class BridgeConnectionState { @HiveField(0) - final String accessToken; + final String deviceToken; @HiveField(1) - final String refreshToken; + final String bridgeUrl; @HiveField(2) - final DateTime expiresAt; + final DateTime pairedAt; @HiveField(3) - final String tokenType; // "oauth" | "pat" + final String tokenType; // "device_pairing" } ``` diff --git a/docs/idea.md b/docs/idea.md index a7819c2..d2d64b9 100644 --- a/docs/idea.md +++ b/docs/idea.md @@ -1,6 +1,6 @@ # ReCursor — Project Concept -> **Mobile-first AI coding agent controller** — Control Claude Code and other AI coding assistants from your mobile device (iOS/Android) with an OpenCode-inspired UI. +> **Mobile-first AI coding agent companion** — Connect to your user-controlled desktop bridge to observe and interact with Claude Code and other AI coding assistants from your mobile device (iOS/Android) with an OpenCode-inspired UI. Bridge-first, no-login workflow. --- @@ -46,21 +46,23 @@ flowchart LR App["ReCursor Flutter App\n(OpenCode-like UI)"] end - subgraph DevMachine["💻 Development Machine"] - Bridge["Bridge Server"] + subgraph DevMachine["💻 User-Controlled Development Machine"] + Bridge["ReCursor Bridge Server"] CCHooks["Claude Code Hooks\n(Event Observer)"] CC["Claude Code CLI"] end - App <-->|WebSocket| Bridge - Bridge <-->|HTTP| CCHooks + App <-->|WebSocket (wss://)| Bridge + Bridge <-->|HTTP POST| CCHooks CCHooks -->|Observes| CC ``` **Integration Strategy:** -- **Event Source**: Claude Code Hooks POST events to the bridge server +- **Bridge-First**: Mobile app connects directly to user-controlled bridge (no hosted service, no login) +- **Event Source**: Claude Code Hooks POST events to the bridge server (one-way observation) - **UI Pattern**: OpenCode-style tool cards, diff viewer, session timeline -- **Session Model**: Parallel Agent SDK sessions (not direct mirroring) +- **Session Model**: Parallel Agent SDK sessions (not mirroring existing Claude Code sessions) +- **Remote Access**: Secure tunnel (Tailscale, WireGuard) to your own bridge — not unsupported third-party Claude Remote Control --- @@ -71,7 +73,7 @@ flowchart LR | Framework | Flutter | Cross-platform, CC Pocket precedent | | State | Riverpod | Type-safe, testable, Conduit pattern | | Networking | `web_socket_channel` | Standard Flutter WebSocket | -| Auth | GitHub OAuth2 + PAT | `github_oauth` package | +| Device Pairing | QR code + token | Bridge-first connection | | Local DB | Drift (SQLite) | Type-safe queries, migrations | | Cache | Hive | Fast key-value for ephemeral data | | Bridge | TypeScript (Node.js) | CC Pocket pattern | diff --git a/docs/integration/agent-sdk.md b/docs/integration/agent-sdk.md index a7d8c15..0555061 100644 --- a/docs/integration/agent-sdk.md +++ b/docs/integration/agent-sdk.md @@ -1,6 +1,6 @@ # Agent SDK Integration -> Using the Claude Agent SDK for parallel agent sessions in ReCursor. +> Using the Claude Agent SDK for parallel agent sessions in ReCursor. This is a supported integration path — ReCursor does not claim to mirror or control existing Claude Code sessions via unsupported Remote Control protocols. --- @@ -88,7 +88,7 @@ const agent = new Agent({ // Start a conversation const response = await agent.run({ - messages: [{ role: 'user', content: 'Fix the auth bug in login.dart' }], + messages: [{ role: 'user', content: 'Tighten the bridge startup validation in bridge_setup_screen.dart' }], }); ``` diff --git a/docs/integration/claude-code-hooks.md b/docs/integration/claude-code-hooks.md index e9e17b6..cd16ae4 100644 --- a/docs/integration/claude-code-hooks.md +++ b/docs/integration/claude-code-hooks.md @@ -1,6 +1,6 @@ # Claude Code Hooks Integration -> Configure Claude Code Hooks to POST events to the ReCursor bridge server for mobile consumption. +> Configure Claude Code Hooks to POST events to the ReCursor bridge server for mobile consumption. This is a supported integration path for one-way event observation — not a Remote Control protocol. --- @@ -340,9 +340,9 @@ eventBus.on('claude-event', broadcastToMobile); "session_id": "sess-abc123", "timestamp": "2026-03-17T10:35:00Z", "payload": { - "prompt": "Add error handling to the login function", + "prompt": "Add error handling to the bridge setup reconnect flow", "context": { - "current_file": "lib/auth.dart", + "current_file": "lib/features/startup/bridge_setup_screen.dart", "cursor_position": 145 } } diff --git a/docs/legal/privacy-policy.md b/docs/legal/privacy-policy.md index 42c2dec..a6368e8 100644 --- a/docs/legal/privacy-policy.md +++ b/docs/legal/privacy-policy.md @@ -8,8 +8,8 @@ ReCursor ("we", "our", "the app") is an open-source mobile application for monit ## Data We Collect ### Data stored locally on your device -- **Authentication tokens**: GitHub OAuth tokens or Personal Access Tokens, stored in your device's secure keychain -- **Agent configurations**: Bridge server URLs and auth tokens, stored encrypted in the app's local database +- **Bridge connection**: Bridge server URLs and device pairing tokens, stored encrypted via secure keychain +- **Agent configurations**: Working directories and agent preferences, stored in the app's local database - **Session history**: Chat messages and tool call records from your AI agent sessions, stored locally in SQLite - **App preferences**: Theme settings and notification preferences, stored in local key-value storage @@ -25,16 +25,15 @@ If you explicitly enable analytics in Settings, the app logs anonymized usage ev ## Data Transmission ReCursor communicates only with: 1. **Your bridge server**: The app connects directly to the ReCursor bridge server running on your own machine via WebSocket. You control this server. -2. **GitHub API**: Only for authentication (OAuth token exchange or PAT validation). We do not store GitHub API responses beyond the access token. -3. **Anthropic API**: If using the Agent SDK integration, requests are made via your bridge server using your own API key. ReCursor does not have access to your Anthropic API key. +2. **Anthropic API**: If using the Agent SDK integration, requests are made via your bridge server using your own API key. ReCursor does not have access to your Anthropic API key. ## Security -- Authentication tokens are stored using iOS Keychain / Android Keystore via `flutter_secure_storage` +- Bridge pairing tokens are stored using iOS Keychain / Android Keystore via `flutter_secure_storage` - All bridge connections use WSS (TLS-encrypted WebSocket) - We recommend using Tailscale or WireGuard for bridge connectivity ## Your Rights -You can delete all locally stored data by uninstalling the app or using "Sign Out" in Settings. +You can delete all locally stored data by uninstalling the app or using "Reset App" in Settings. ## Changes We will update this policy as the app evolves. Check the app's GitHub repository for the latest version. diff --git a/docs/project-structure.md b/docs/project-structure.md index bcc8da9..cf179ec 100644 --- a/docs/project-structure.md +++ b/docs/project-structure.md @@ -32,7 +32,7 @@ recursor/ │ │ ├── hooks/ # Claude Code Hooks receiver │ │ ├── git/ # Git operation handlers │ │ ├── terminal/ # Terminal session manager -│ │ ├── auth/ # Token validation, rate limiting +│ │ ├── auth/ # Device token validation, rate limiting │ │ └── notifications/ # Event queue + WebSocket dispatch │ ├── package.json │ └── tsconfig.json @@ -64,13 +64,12 @@ core/ │ ├── websocket_messages.dart # Message type definitions (from bridge-protocol.md) │ └── connection_state.dart # Connection state enum + notifier │ -├── auth/ -│ ├── auth_provider.dart # Riverpod auth state provider -│ ├── auth_repository.dart # OAuth + PAT token management -│ ├── token_storage.dart # flutter_secure_storage wrapper -│ └── github_oauth.dart # OAuth2 flow handler +├── providers/ +│ ├── token_storage_provider.dart # Secure bridge token storage provider +│ └── websocket_provider.dart # Shared WebSocket service providers │ ├── storage/ +│ ├── secure_token_storage.dart # flutter_secure_storage wrapper for bridge pairing │ ├── database.dart # Drift database definition │ ├── tables/ # Drift table definitions │ │ ├── sessions.dart @@ -231,19 +230,13 @@ features/ │ └── widgets/ │ └── agent_card.dart │ -├── auth/ # Authentication -│ ├── data/ -│ │ └── repositories/ -│ │ └── auth_repository.dart +├── startup/ # Bridge-first launch and pairing restore │ ├── domain/ -│ │ └── providers/ -│ │ └── auth_provider.dart +│ │ └── bridge_startup_controller.dart │ └── presentation/ -│ ├── screens/ -│ │ ├── login_screen.dart -│ │ └── splash_screen.dart -│ └── widgets/ -│ └── auth_button.dart +│ └── screens/ +│ ├── splash_screen.dart +│ └── bridge_setup_screen.dart │ └── settings/ # App settings └── presentation/ @@ -311,7 +304,7 @@ bridge/ │ └── output_stream.ts # Terminal output streaming │ ├── auth/ -│ ├── token_validator.ts # JWT/auth token validation +│ ├── token_validator.ts # Device pairing token validation │ └── rate_limiter.ts # Rate limiting │ └── notifications/ diff --git a/docs/push-notifications.md b/docs/push-notifications.md index c0625a9..c26e7b7 100644 --- a/docs/push-notifications.md +++ b/docs/push-notifications.md @@ -55,8 +55,8 @@ All notifications flow through the existing WebSocket connection. No external pu "payload": { "session_id": "sess-abc123", "notification_type": "approval_required", - "title": "Approval needed: Edit login.dart", - "body": "Claude Code wants to change the OAuth callback URL.", + "title": "Approval needed: Update bridge_setup_screen.dart", + "body": "Claude Code wants to tighten bridge URL validation before pairing.", "priority": "high", "data": { "tool_call_id": "tool-001", diff --git a/docs/research.md b/docs/research.md index 1087fce..3c59b8a 100644 --- a/docs/research.md +++ b/docs/research.md @@ -64,6 +64,8 @@ The emerging architectural pattern across all mobile coding agent clients is a * ## Flutter GitHub client apps provide battle-tested architectural patterns +> **Note:** This section documents GitHub OAuth patterns as prior research for mobile GitHub client architecture. ReCursor's current direction is **bridge-first with no user authentication** — repository operations are delegated to the agent running on the development machine. Git operations via bridge commands, not native mobile OAuth. + For GitHub OAuth, repository browsing, and git operations on mobile, three codebases stand out as architectural references. **GSYGithubAppFlutter** ([CarGuo/gsy_github_app_flutter](https://github.com/CarGuo/gsy_github_app_flutter)) at **15.4K stars** is the definitive Flutter GitHub client. Updated through February 2026, it uniquely demonstrates Redux, Provider, Riverpod, and Signals state management in the same project. Its four-layer architecture (UI → State → Service → Data) with repository pattern, event bus, and SQL caching provides a complete blueprint. Features include full GitHub OAuth (using custom URL scheme `gsygithubapp://authed`), repo/issue/PR browsing, trending repos, search, markdown rendering, and i18n. **Apache 2.0 licensed** with 2.6K forks. diff --git a/docs/security-architecture.md b/docs/security-architecture.md index 5be7d0d..6b6e52b 100644 --- a/docs/security-architecture.md +++ b/docs/security-architecture.md @@ -6,13 +6,13 @@ ## Network Layer -- **Use Tailscale as the primary networking layer.** It wraps WireGuard encryption, handles NAT traversal, and creates a zero-config mesh VPN between phone and dev machine. DERP relay servers never see unencrypted data. -- **Always use `wss://` (WebSocket Secure).** TLS at the application layer + WireGuard at the network layer = defense in depth. -- **Never expose the bridge on a public IP.** The bridge should only be reachable within the Tailscale network or via SSH tunnel. +- **Use a secure tunnel for remote access.** Tailscale (recommended) wraps WireGuard encryption, handles NAT traversal, and creates a zero-config mesh VPN between phone and dev machine. DERP relay servers never see unencrypted data. Other options include WireGuard, Cloudflare Tunnel, or SSH tunneling. +- **Always use `wss://` (WebSocket Secure).** TLS at the application layer + tunnel encryption at the network layer = defense in depth. +- **Never expose the bridge on a public IP without tunnel protection.** The bridge should only be reachable within your secure tunnel network. --- -## Authentication Flow +## Bridge Connection Security ```mermaid sequenceDiagram @@ -20,9 +20,9 @@ sequenceDiagram participant Bridge as Bridge Server participant Hooks as Claude Code Hooks - Note over Mobile,Hooks: Connection Authentication - Mobile->>Bridge: wss:// + auth_token - Bridge->>Bridge: Validate token (Firebase/JWT) + Note over Mobile,Hooks: Connection Pairing + Mobile->>Bridge: wss:// connect + device_token + Bridge->>Bridge: Validate device_token Bridge-->>Mobile: connection_ack Note over Mobile,Hooks: Hook Event Authentication @@ -35,21 +35,21 @@ sequenceDiagram | Token Type | Purpose | Storage | |------------|---------|---------| -| Bridge Auth Token | Authenticate mobile app to bridge | `flutter_secure_storage` | +| Device Pairing Token | Authenticate mobile app to bridge (generated at pairing) | `flutter_secure_storage` | | Hook Token | Authenticate Claude Code Hooks to bridge | Bridge server env only | -| GitHub OAuth Token | GitHub API access | `flutter_secure_storage` | -| GitHub PAT | Fallback auth | `flutter_secure_storage` | --- ## Token Management -### Bridge Auth Token +### Device Pairing Token -- **Generate**: 32+ character random string (crypto-safe) -- **Storage**: Bridge server environment variable +- **Generate**: 32+ character random string (crypto-safe), generated during bridge setup +- **Storage**: Bridge server environment variable or config file - **Mobile**: Encrypted with `flutter_secure_storage` (Keychain/EncryptedSharedPreferences) - **QR Code**: Bridge URL + token encoded for easy pairing +- **No User Accounts**: Tokens are per-device, not tied to any user identity or hosted account +- **Bridge-First**: No login flow — the app opens to bridge pairing/restore, not sign-in ```dart // Token generation (bridge server) @@ -59,9 +59,9 @@ const token = crypto.randomBytes(32).toString('hex'); // 64 chars ### Token Rotation -- Rotate bridge auth tokens on suspicious activity -- Invalidate tokens on logout -- Support token revocation list +- Rotate device tokens if bridge is reinstalled or security concern arises +- Clear token from mobile app via "Disconnect Bridge" in Settings +- Support token revocation list on bridge server --- diff --git a/docs/testing-strategy.md b/docs/testing-strategy.md index b8a754b..37a8c56 100644 --- a/docs/testing-strategy.md +++ b/docs/testing-strategy.md @@ -55,7 +55,7 @@ expectLater( ### What to Unit Test - WebSocket service (connect, disconnect, reconnect, message parsing) -- Auth provider state transitions (unauthenticated -> authenticating -> authenticated -> error) +- Bridge connection state transitions (disconnected -> connecting -> connected -> error) - Git command serialization/deserialization - Notification payload parsing - Diff parsing logic @@ -88,7 +88,7 @@ testWidgets('shows connected status', (tester) async { ### What to Widget Test - Chat UI with mock message streams -- Login screen form validation and submission +- Bridge QR pairing screen - OpenCode-style Tool Cards with sample data - Diff viewer with sample diff data - Approval UI approve/reject/modify interactions @@ -167,7 +167,7 @@ testWidgets('full chat flow', (tester) async { ### What to Integration Test -- Auth -> connect -> chat -> receive response +- Bridge connect -> validate pairing -> chat -> receive response - Git operation flows (commit, push, pull) - Approval flow (receive tool call -> approve -> agent continues) - Offline -> reconnect -> sync @@ -213,7 +213,7 @@ class TestBridgeServer { ### E2E Scenarios -- Full onboarding flow: install -> auth -> pair -> first message +- Full onboarding flow: install -> bridge pairing -> first message - Background notification: receive approval request -> tap notification -> approve - Multi-session: switch between agent sessions - Offline workflow: actions while offline -> sync on reconnect diff --git a/docs/wireframes/03-chat.md b/docs/wireframes/03-chat.md index e4e436f..1b15731 100644 --- a/docs/wireframes/03-chat.md +++ b/docs/wireframes/03-chat.md @@ -12,9 +12,9 @@ +---------------------------------------+ | | | +----------------------------------+ | -| | Fix auth bug in login.dart | | +| | Improve bridge reconnect banner | | | | Claude Code * 2 min ago | | -| | "I've updated the OAuth..." | | +| | "I've updated the reconnect..." | | | +----------------------------------+ | | | | +----------------------------------+ | @@ -52,29 +52,29 @@ ``` +---------------------------------------+ -| [<] Fix auth bug (*) Connected | +| [<] Bridge reconnect (*) Connected | | Claude Code * main branch | +---------------------------------------+ | | | +----------------------------------+ | | | You 10:32 AM | | -| | Fix the OAuth redirect bug in | | -| | lib/auth/login.dart. The | | -| | callback URL is wrong. | | +| | Tighten the bridge startup | | +| | validation in | | +| | lib/features/startup/... | | | +----------------------------------+ | | | | +-----------------------------+| | | Claude Code 10:32 AM || | | || -| | I'll fix the OAuth redirect || -| | in `login.dart`. The issue || -| | is on line 42 where the || -| | callback URL uses `http` || -| | instead of `https`. || +| | I'll tighten the bridge || +| | validation in the startup || +| | screen. The saved URL must || +| | continue using `wss://` || +| | before the app reconnects. || | | || | | ```dart || | | // Before || -| | callbackUrl: 'http://...' || +| | bridgeUrl: 'ws://...' || | | // After || | | callbackUrl: 'https://...' || | | ``` || @@ -118,7 +118,7 @@ ``` +---------------------------------------+ -| [<] Fix auth bug (*) Connected | +| [<] Bridge startup (*) Connected | +---------------------------------------+ | | | ... (previous messages) ... | @@ -130,11 +130,11 @@ | | || | | +-------------------------+ || | | | TOOL: Edit File | || -| | | File: lib/auth/login.da | || +| | | File: startup/splash... | || | | | Lines: 42-45 | || | | | | || -| | | - url: 'http://cb' | || -| | | + url: 'https://cb' | || +| | | - allowWs(url); | || +| | | + requireWss(url); | || | | | | || | | | [Approve] [Reject] | || | | | [View Full] [Modify] | || @@ -156,7 +156,7 @@ ``` +---------------------------------------+ -| [<] Fix auth bug (*) Connected | +| [<] Bridge startup (*) Connected | +---------------------------------------+ | | | ... (previous messages) ... | diff --git a/docs/wireframes/04-repos.md b/docs/wireframes/04-repos.md index e48020d..6517e44 100644 --- a/docs/wireframes/04-repos.md +++ b/docs/wireframes/04-repos.md @@ -62,11 +62,11 @@ | lib/ | | > core/ | | v features/ | -| v auth/ | -| > data/ | +| v startup/ | | > domain/ | -| login_screen.dart | -| auth_provider.dart | +| bridge_startup_controller.. | +| bridge_setup_screen.dart | +| splash_screen.dart | | > chat/ | | > repos/ | | > shared/ | @@ -99,18 +99,18 @@ ``` +---------------------------------------+ -| [<] login_screen.dart [...] | -| lib/features/auth/ * 142 lines | +| [<] bridge_setup_screen.dart [...] | +| lib/features/startup/ * 196 lines | +---------------------------------------+ | 1 | import 'package:flutter/mat.. | | 2 | import 'package:riverpod/ri.. | | 3 | | -| 4 | class LoginScreen extends St.. | +| 4 | class BridgeSetupScreen exte.. | | 5 | @override | | 6 | Widget build(BuildContext c.. | | 7 | return Scaffold( | | 8 | appBar: AppBar( | -| 9 | title: Text('Login'), | +| 9 | title: Text('Bridge Setup'),| | 10 | ), | | 11 | body: Padding( | | 12 | padding: EdgeInsets... | diff --git a/docs/wireframes/05-git.md b/docs/wireframes/05-git.md index d9cd78a..726eae5 100644 --- a/docs/wireframes/05-git.md +++ b/docs/wireframes/05-git.md @@ -25,10 +25,10 @@ | | | Recent Activity | | +----------------------------------+ | -| | abc1234 Fix OAuth redirect | | +| | abc1234 Tighten bridge startup | | | | Nathan * 2 hours ago | | | +----------------------------------+ | -| | def5678 Add auth provider | | +| | def5678 Add pairing restore | | | | Nathan * 5 hours ago | | | +----------------------------------+ | | | ghi9012 Initial project setup | | @@ -65,7 +65,7 @@ | | feature/voice-input | | | | origin/feature/voice * +3 | | | +----------------------------------+ | -| | fix/oauth-redirect | | +| | fix/bridge-startup | | | | (no remote) * local only | | | +----------------------------------+ | | | @@ -126,20 +126,20 @@ | | | Commit message: | | +----------------------------------+ | -| | Fix OAuth redirect bug | | +| | Tighten bridge startup | | | +----------------------------------+ | -| | Updated callback URL from http | | -| | to https in login.dart. Added | | -| | validation for redirect URIs. | | +| | Require WSS bridge URLs and | | +| | keep the saved pairing token | | +| | before restoring the session. | | | | | | | +----------------------------------+ | | | | Changed files: [Select All] | | +----------------------------------+ | -| | [x] M lib/auth/login.dart | | +| | [x] M lib/features/startup/... | | | | +2 -1 [>] | | | +----------------------------------+ | -| | [x] M lib/auth/oauth.dart | | +| | [x] M test/startup_restore.. | | | | +15 -3 [>] | | | +----------------------------------+ | | | [ ] ? test/auth_test.dart | | @@ -191,8 +191,8 @@ | Push complete! | | | | 3 commits pushed to origin/main | -| abc1234 Fix OAuth redirect | -| def5678 Add URL validation | +| abc1234 Tighten bridge startup | +| def5678 Add session restore | | ghi9012 Update tests | | | | [ Done ] | diff --git a/docs/wireframes/06-diff.md b/docs/wireframes/06-diff.md index 7046962..2cc573d 100644 --- a/docs/wireframes/06-diff.md +++ b/docs/wireframes/06-diff.md @@ -9,25 +9,25 @@ ``` +---------------------------------------+ | [<] Changes 3 files changed| -| abc1234 Fix OAuth redirect | +| abc1234 Tighten bridge startup | +---------------------------------------+ | | | +5 -2 across 3 files | | | | +----------------------------------+ | -| | lib/auth/login.dart | | +| | lib/features/startup/splash... | | | | +2 -1 | | | | ████████░░ 80% changed | | | +----------------------------------+ | | | | +----------------------------------+ | -| | lib/auth/oauth.dart | | +| | lib/features/startup/bridge... | | | | +2 -1 | | | | ██░░░░░░░░ 20% changed | | | +----------------------------------+ | | | | +----------------------------------+ | -| | test/auth_test.dart | | +| | test/startup_restore_test.dart | | | | +1 -0 (new file) | | | | ██████████ 100% new | | | +----------------------------------+ | @@ -49,18 +49,18 @@ ``` +---------------------------------------+ -| [<] login.dart [Unified|Split] | +| [<] bridge_setup_screen.dart [Unified|Split] | | File 1 of 3 [< prev][next >]| +---------------------------------------+ | | -| @@ -40,7 +40,8 @@ class LoginScr... | +| @@ -40,7 +40,8 @@ class BridgeSet... | | | -| 40 | final config = OAuthConfig( | -| 41 | clientId: env.clientId, | -| 42 |- callbackUrl: 'http://localhost' | -| 42 |+ callbackUrl: 'https://localhos' | -| 43 |+ redirectValidation: true, | -| 44 | ); | +| 40 | final result = validator( | +| 41 | url: normalizedUrl, | +| 42 |- allowWs: true, | +| 42 |+ requireWss: true, | +| 43 |+ ensureTokenPresent: true, | +| 44 | ); | | 45 | | | | | @@ -78,4 +79,4 @@ void _handleRe... | @@ -92,18 +92,18 @@ ``` +-------------------------------------------------------------------+ -| [<] login.dart [Unified|Split] [< prev] [next >] | +| [<] bridge_setup_screen.dart [Unified|Split] [< prev] [next >] | +-------------------------------------------------------------------+ | OLD | NEW | +------------------------------+------------------------------------+ -| 40 | final config = OAuth.. | 40 | final config = OAuth.. | -| 41 | clientId: env.client.. | 41 | clientId: env.client.. | -| 42 | callbackUrl: 'http://. | 42 | callbackUrl: 'https://. | -| | | 43 | redirectValidation: true, | +| 40 | final validator = Br.. | 40 | final validator = Br.. | +| 41 | url: normalizedUrl, | 41 | url: normalizedUrl, | +| 42 | allowWs: true, | 42 | requireWss: true, | +| | | 43 | ensureTokenPresent: true, | | 43 | ); | 44 | ); | | | | | -| 78 | if (uri.scheme != ... | 79 | if (uri.scheme != ... | -| 79 | throw AuthError('Inv.. | 79 | throw AuthError('Invalid p.. | +| 78 | if (token.isEmpty) .. | 79 | if (token.isEmpty) .. | +| 79 | return invalid(..) | 79 | return invalid(..) | | 80 | } | 80 | } | +------------------------------+------------------------------------+ ``` @@ -121,7 +121,7 @@ +---------------------------------------+ | | | Comment on line 42: | -| login.dart | +| bridge_setup_screen.dart | | | | +----------------------------------+| | | Should we also update the || diff --git a/docs/wireframes/07-approvals.md b/docs/wireframes/07-approvals.md index a082be8..2a985d0 100644 --- a/docs/wireframes/07-approvals.md +++ b/docs/wireframes/07-approvals.md @@ -14,10 +14,10 @@ | Claude Code wants to: | | | | Edit File | -| lib/auth/login.dart | +| lib/features/startup/bridge_... | | | -| - callbackUrl: 'http://...' | -| + callbackUrl: 'https://...' | +| - allowWs: true | +| + requireWss: true | | | | [View Full Diff] | | | @@ -39,28 +39,28 @@ | | | +----------------------------------+ | | | Agent: Claude Code | | -| | Session: Fix auth bug | | +| | Session: Bridge startup | | | | Time: 10:33 AM | | | +----------------------------------+ | | | | Tool: Edit File | -| File: lib/auth/login.dart | +| File: lib/features/startup/... | | Lines: 42-45 | | | | Changes: | | +----------------------------------+ | | | @@ -40,7 +40,8 @@ | | -| | 40 | final config = OAuthConf.. | | -| | 41 | clientId: env.clientId, | | -| | 42 |- callbackUrl: 'http://.. | | -| | 42 |+ callbackUrl: 'https://.. | | -| | 43 |+ redirectValidation: true, | | +| | 40 | final validator = Bridge.. | | +| | 41 | if (url.isEmpty) return... | | +| | 42 |- return wsAllowed(url); | | +| | 42 |+ return wssRequired(url); | | +| | 43 |+ ensureTokenPresent(); | | | +----------------------------------+ | | | | Agent reasoning: | -| "The callback URL must use HTTPS | -| for OAuth security. I'm also | -| adding redirect validation." | +| "The bridge URL must use WSS and | +| the pairing token cannot be empty. | +| I'm tightening startup validation."| | | +---------------------------------------+ | [ Approve ] [ Reject ] | @@ -108,9 +108,9 @@ ``` +---------------------------------------+ | ReCursor now | -| Approval needed: Edit login.dart | -| Claude Code wants to change the | -| OAuth callback URL. | +| Approval needed: Bridge setup edit | +| Claude Code wants to tighten the | +| startup bridge validation. | | | | [ Approve ] [ View ] | +---------------------------------------+ @@ -133,7 +133,7 @@ | Today | | +----------------------------------+ | | | [check] Approved | | -| | Edit lib/auth/login.dart | | +| | Edit bridge_setup_screen.dart | | | | Claude Code * 10:33 AM | | | +----------------------------------+ | | | [check] Approved | | diff --git a/docs/wireframes/08-terminal.md b/docs/wireframes/08-terminal.md index 651c2cc..199c844 100644 --- a/docs/wireframes/08-terminal.md +++ b/docs/wireframes/08-terminal.md @@ -17,8 +17,8 @@ | $ git status | | On branch main | | Changes not staged for commit: | -| modified: lib/auth/login.dart | -| modified: lib/auth/oauth.dart | +| modified: lib/features/startup/bridge_setup_screen.dart | +| modified: lib/features/startup/splash_screen.dart | | | | Untracked files: | | test/auth_test.dart | diff --git a/docs/wireframes/09-agents.md b/docs/wireframes/09-agents.md index 5608e06..ce029aa 100644 --- a/docs/wireframes/09-agents.md +++ b/docs/wireframes/09-agents.md @@ -71,7 +71,7 @@ | | wss://100.78.42.15:3000 | | | +----------------------------------+ | | | -| Auth token: | +| Pairing token: | | +----------------------------------+ | | | ******************************** | | | +----------------------------------+ | diff --git a/docs/wireframes/10-settings.md b/docs/wireframes/10-settings.md index eee1360..392fce1 100644 --- a/docs/wireframes/10-settings.md +++ b/docs/wireframes/10-settings.md @@ -11,12 +11,6 @@ | [=] Settings | +---------------------------------------+ | | -| ACCOUNT | -| +----------------------------------+ | -| | GitHub Account | | -| | @username [>] | | -| +----------------------------------+ | -| | | CONNECTIONS | | +----------------------------------+ | | | My Agents | | @@ -58,7 +52,7 @@ | | Open Source Licenses | | | +----------------------------------+ | | | -| [ Sign Out ] | +| [ Disconnect Bridge ] | | | +---------------------------------------+ | Agent | Repos | Git | Settings | @@ -67,26 +61,25 @@ --- -## 10B. Account +## 10B. Bridge Connection ``` +---------------------------------------+ -| [<] Account | +| [<] Bridge Connection | +---------------------------------------+ | | -| [ avatar image ] | -| @username | +| [ App Icon ] | | | | +----------------------------------+ | -| | Auth method | | -| | GitHub OAuth | | +| | Bridge URL | | +| | wss://100.x.x.x:3000 [>] | | | +----------------------------------+ | -| | Token expires | | -| | March 20, 2026 | | +| | Device paired | | +| | March 20, 2026 | | | +----------------------------------+ | | | -| [ Re-authenticate ] | -| [ Switch Account ] | +| [ Re-pair Bridge ] | +| [ Reset Connection ] | | | +---------------------------------------+ ``` diff --git a/docs/wireframes/11-tablet.md b/docs/wireframes/11-tablet.md index 52e5f1d..e467967 100644 --- a/docs/wireframes/11-tablet.md +++ b/docs/wireframes/11-tablet.md @@ -13,17 +13,17 @@ | | | | CHAT | DIFF / FILE VIEWER | | | | -| +------------------------+ | login.dart | +| +------------------------+ | bridge_setup_screen.dart | | | You 10:32 AM | | | -| | Fix the OAuth redirect | | @@ -40,7 +40,8 @@ | -| | bug in login.dart | | | -| +------------------------+ | 40 | final config = OAu.. | -| | 41 | clientId: env.cli.. | -| +------------------------+ | 42 |- callbackUrl: 'http.. | -| | Claude Code 10:32 AM | | 42 |+ callbackUrl: 'https.. | -| | | | 43 |+ redirectValidation.. | -| | I'll fix the OAuth | | 44 | ); | -| | redirect. The issue | | | +| | Tighten bridge startup | | @@ -40,7 +40,8 @@ | +| | validation flow | | | +| +------------------------+ | 40 | final validator = Br.. | +| | 41 | if (url.isEmpty) re.. | +| +------------------------+ | 42 |- return allowWs(url); | +| | Claude Code 10:32 AM | | 42 |+ return requireWss(url); | +| | | | 43 |+ ensureTokenPresent(); | +| | I'll tighten the | | 44 | ); | +| | bridge startup flow. | | | | | is on line 42... | | | | | | | | | | [View Diff] | | | @@ -52,14 +52,14 @@ | | | | FILE TREE | FILE VIEWER | | | | -| lib/ | login_screen.dart | -| v core/ | lib/features/auth/ * 142 lines | +| lib/ | bridge_setup_screen.dart | +| v core/ | lib/features/startup/ * 196 lines | | v features/ | | -| v auth/ | 1 | import 'package:flu.. | -| > data/ | 2 | import 'package:riv.. | -| > domain/ | 3 | | -| * login_screen.dart | 4 | class LoginScreen e.. | -| auth_provider.dart | 5 | @override | +| v startup/ | 1 | import 'package:flu.. | +| > domain/ | 2 | import 'package:riv.. | +| * bridge_setup_.. | 3 | | +| * splash_screen.dart | 4 | class BridgeSetupScreen.. | +| bridge_startup.. | 5 | @override | | > chat/ | 6 | Widget build(Buil.. | | > repos/ | 7 | return Scaffold( | | > shared/ | 8 | appBar: AppBar( | @@ -90,19 +90,19 @@ | | | | COMMIT | DIFF PREVIEW | | | | -| Message: | login.dart | +| Message: | bridge_setup_screen.dart | | +------------------------+ | | -| | Fix OAuth redirect bug | | @@ -40,7 +40,8 @@ | -| +------------------------+ | 40 | final config = OA.. | -| +------------------------+ | 41 | clientId: env.cl.. | -| | Updated callback URL | | 42 |- callbackUrl: 'ht.. | -| | from http to https... | | 42 |+ callbackUrl: 'ht.. | -| +------------------------+ | 43 |+ redirectValidati.. | +| | Tighten bridge startup | | @@ -40,7 +40,8 @@ | +| +------------------------+ | 40 | final validator = Br.. | +| +------------------------+ | 41 | if (url.isEmpty) re.. | +| | Require WSS and a | | 42 |- return allowWs(url); | +| | pairing token first... | | 42 |+ return requireWss(url); | +| +------------------------+ | 43 |+ ensureTokenPresent(); | | | | -| Files: | oauth.dart | -| [x] M login.dart [>] | | -| [x] M oauth.dart [>]| @@ -12,3 +12,5 @@ | -| [ ] ? auth_test.dart [>]| 12 | validateRedirect(.. | +| Files: | bridge_setup_screen.dart | +| [x] M splash_screen.. [>] | | +| [x] M bridge_setup.. [>]| @@ -12,3 +12,5 @@ | +| [ ] ? startup_test.. [>]| 12 | requireWss(.. | | | 13 |+ if (!uri.isScheme.. | | [ Commit ] | | | | | @@ -131,8 +131,8 @@ | $ git status | | On branch main | | Changes not staged for commit: | -| modified: lib/auth/login.dart | -| modified: lib/auth/oauth.dart | +| modified: lib/features/startup/bridge_setup_screen.dart | +| modified: lib/features/startup/splash_screen.dart | | | | $ _ | +-------------------------------------------------------------------+ diff --git a/docs/wireframes/README.md b/docs/wireframes/README.md index 0190f12..a67893a 100644 --- a/docs/wireframes/README.md +++ b/docs/wireframes/README.md @@ -1,30 +1,33 @@ # ReCursor - UI/UX Wireframes > Modular ASCII wireframes for every screen in the mobile app. -> Each file maps to a feature module. Screens are ordered by user flow. +> Each file maps to a feature module. Screens are ordered by the bridge-first, no-login user flow. --- -## Navigation Architecture +## Navigation Architecture (Bridge-First, No-Login) ``` +------------------+ - | Splash Screen | + | Splash / Restore | + | (No login screen) | +--------+---------+ | - +--------v---------+ - | Login Screen | - +--------+---------+ + +--------------v--------------+ + | Saved Pairing? | + | (Restore or New Pairing) | + +--------------+--------------+ | +--------v---------+ - | Bridge Pairing | + | Bridge Setup | + | (QR Pairing) | +--------+---------+ | +--------------v--------------+ | Main Shell (Bottom Nav) | +-+--------+--------+--------+-+ | | | | - +---v--+ +---v--+ +---v--+ +---v------+ + +---v--+ +---v--+ +---v--+ +---v------+ | Chat | | Repos| | Git | | Settings | +---+--+ +---+--+ +---+--+ +----------+ | | | @@ -34,6 +37,8 @@ +-------+ +-------+ +----------+ ``` +**Key:** No login screen, no user accounts — the app opens directly to bridge pairing restoration or setup. + ## Bottom Navigation Tabs ``` @@ -47,7 +52,7 @@ | File | Screens | Phase | |------|---------|-------| -| [`01-auth.md`](01-auth.md) | Splash, Login, OAuth WebView | 1 | +| [`01-startup.md`](01-startup.md) | Splash, Saved Pairing Restore, Startup Fallback | 1 | | [`02-bridge.md`](02-bridge.md) | QR Pairing, Connection Status | 1 | | [`03-chat.md`](03-chat.md) | Chat, Session List, Streaming, Voice Input | 1, 3 | | [`04-repos.md`](04-repos.md) | Repo List, File Tree, File Viewer | 1 | From e21ea7cbf09227c409753aefde284da534483863 Mon Sep 17 00:00:00 2001 From: Fury3K Date: Fri, 20 Mar 2026 15:24:07 +0800 Subject: [PATCH 22/22] feat(docs): add documentation site with GitHub Pages deployment Static documentation site modeled after code.claude.com/docs with: - Modular page architecture (12 pages loaded via fetch) - Dark theme with sidebar navigation and search (Ctrl+K) - Copy code, copy as markdown, and copy page features - ReCursor SVG branding throughout - GitHub Actions workflow for auto-deploy to Pages --- .github/workflows/docs.yml | 56 ++ docs-site/app.js | 558 +++++++++++++ docs-site/assets/logo.svg | 21 + docs-site/index.html | 119 +++ docs-site/pages/agent-sdk.html | 111 +++ docs-site/pages/architecture.html | 143 ++++ docs-site/pages/bridge-protocol.html | 208 +++++ docs-site/pages/data-flow.html | 67 ++ docs-site/pages/hooks.html | 150 ++++ docs-site/pages/offline.html | 91 ++ docs-site/pages/overview.html | 115 +++ docs-site/pages/quickstart.html | 76 ++ docs-site/pages/roadmap.html | 80 ++ docs-site/pages/security.html | 101 +++ docs-site/pages/tech-stack.html | 82 ++ docs-site/pages/ui-patterns.html | 102 +++ docs-site/styles.css | 1144 ++++++++++++++++++++++++++ 17 files changed, 3224 insertions(+) create mode 100644 .github/workflows/docs.yml create mode 100644 docs-site/app.js create mode 100644 docs-site/assets/logo.svg create mode 100644 docs-site/index.html create mode 100644 docs-site/pages/agent-sdk.html create mode 100644 docs-site/pages/architecture.html create mode 100644 docs-site/pages/bridge-protocol.html create mode 100644 docs-site/pages/data-flow.html create mode 100644 docs-site/pages/hooks.html create mode 100644 docs-site/pages/offline.html create mode 100644 docs-site/pages/overview.html create mode 100644 docs-site/pages/quickstart.html create mode 100644 docs-site/pages/roadmap.html create mode 100644 docs-site/pages/security.html create mode 100644 docs-site/pages/tech-stack.html create mode 100644 docs-site/pages/ui-patterns.html create mode 100644 docs-site/styles.css diff --git a/.github/workflows/docs.yml b/.github/workflows/docs.yml new file mode 100644 index 0000000..5c10c0f --- /dev/null +++ b/.github/workflows/docs.yml @@ -0,0 +1,56 @@ +name: Deploy Docs to GitHub Pages + +on: + push: + branches: [main] + paths: + - "docs-site/**" + - ".github/workflows/docs.yml" + workflow_dispatch: + +permissions: + contents: read + pages: write + id-token: write + +concurrency: + group: pages + cancel-in-progress: true + +jobs: + deploy: + name: Deploy + runs-on: ubuntu-latest + environment: + name: github-pages + url: ${{ steps.deployment.outputs.page_url }} + + steps: + - uses: actions/checkout@v4 + + - name: Configure GitHub Pages + uses: actions/configure-pages@v5 + + - name: Upload docs-site as Pages artifact + uses: actions/upload-pages-artifact@v3 + with: + path: docs-site + + - name: Deploy to GitHub Pages + id: deployment + uses: actions/deploy-pages@v4 + + update-repo: + name: Update repo metadata + runs-on: ubuntu-latest + needs: deploy + permissions: + contents: read + steps: + - name: Set homepage URL and description + env: + GH_TOKEN: ${{ secrets.GITHUB_TOKEN }} + run: | + gh repo edit RecursiveDev/ReCursor \ + --homepage "https://recursivedev.github.io/ReCursor" \ + --description "Mobile-first companion UI for AI coding workflows - Flutter app with OpenCode-like UX, Claude Code Hooks integration, and Agent SDK support" diff --git a/docs-site/app.js b/docs-site/app.js new file mode 100644 index 0000000..24ab2c7 --- /dev/null +++ b/docs-site/app.js @@ -0,0 +1,558 @@ +// ===== Page Registry ===== +const pages = [ + { id: 'overview', title: 'Overview', section: 'Getting Started' }, + { id: 'architecture', title: 'Architecture', section: 'Getting Started' }, + { id: 'quickstart', title: 'Quickstart', section: 'Getting Started' }, + { id: 'bridge-protocol', title: 'Bridge Protocol', section: 'Core Concepts' }, + { id: 'data-flow', title: 'Data Flow', section: 'Core Concepts' }, + { id: 'offline', title: 'Offline Architecture', section: 'Core Concepts' }, + { id: 'hooks', title: 'Claude Code Hooks', section: 'Integration' }, + { id: 'agent-sdk', title: 'Agent SDK', section: 'Integration' }, + { id: 'ui-patterns', title: 'OpenCode UI Patterns', section: 'Integration' }, + { id: 'security', title: 'Security Architecture', section: 'Security' }, + { id: 'roadmap', title: 'Roadmap', section: 'Development' }, + { id: 'tech-stack', title: 'Tech Stack', section: 'Development' }, +]; + +// ===== Page Cache & State ===== +const pageCache = {}; // id -> HTML string +const searchIndex = {}; // id -> lowercase text for search +let currentPageIndex = 0; + +// ===== Dynamic Page Loading ===== +async function fetchPage(pageId) { + if (pageCache[pageId]) return pageCache[pageId]; + + try { + const resp = await fetch(`pages/${pageId}.html`); + if (!resp.ok) throw new Error(`HTTP ${resp.status}`); + const html = await resp.text(); + pageCache[pageId] = html; + return html; + } catch (err) { + console.error(`Failed to load page: ${pageId}`, err); + return `

`; + } +} + +async function navigateTo(pageId) { + const index = pages.findIndex(p => p.id === pageId); + if (index === -1) return; + currentPageIndex = index; + + const container = document.getElementById('pageContainer'); + + // Show loading state briefly + container.innerHTML = '
'; + + const html = await fetchPage(pageId); + container.innerHTML = html; + + // Build search index for this page if not yet done + if (!searchIndex[pageId]) { + searchIndex[pageId] = container.textContent.toLowerCase(); + } + + // Attach copy handlers on newly-inserted code blocks + attachCopyHandlers(container); + + // Inject "Copy page" button into the page header + injectCopyPageButton(container); + + // Update nav active state + document.querySelectorAll('.nav-item').forEach(item => { + item.classList.toggle('active', item.dataset.page === pageId); + }); + + updateFooterNav(); + window.scrollTo({ top: 0 }); + closeSidebar(); +} + +// ===== Pre-fetch all pages for search index ===== +async function buildSearchIndex() { + await Promise.all(pages.map(async (p) => { + const html = await fetchPage(p.id); + // Parse the text from html for search + const tmp = document.createElement('div'); + tmp.innerHTML = html; + searchIndex[p.id] = tmp.textContent.toLowerCase(); + })); +} + +// ===== Footer Navigation ===== +function updateFooterNav() { + const prevBtn = document.getElementById('footerPrev'); + const nextBtn = document.getElementById('footerNext'); + const prevTitle = document.getElementById('prevTitle'); + const nextTitle = document.getElementById('nextTitle'); + + if (currentPageIndex > 0) { + const prev = pages[currentPageIndex - 1]; + prevBtn.style.display = 'flex'; + prevBtn.href = '#' + prev.id; + prevTitle.textContent = prev.title; + } else { + prevBtn.style.display = 'none'; + } + + if (currentPageIndex < pages.length - 1) { + const next = pages[currentPageIndex + 1]; + nextBtn.style.display = 'flex'; + nextBtn.href = '#' + next.id; + nextTitle.textContent = next.title; + } else { + nextBtn.style.display = 'none'; + } +} + +// ===== Copy Handlers (Code + Markdown) ===== +function attachCopyHandlers(root) { + root.querySelectorAll('.copy-btn').forEach(btn => { + btn.addEventListener('click', () => { + const mode = btn.dataset.mode; // "code" or "markdown" + const block = btn.closest('.code-block'); + const codeEl = block.querySelector('code'); + const rawCode = codeEl.textContent; + + let textToCopy; + if (mode === 'markdown') { + const lang = block.dataset.lang || ''; + // data-md-lang overrides the fence language (e.g. empty for plain text) + const mdLang = block.hasAttribute('data-md-lang') ? block.dataset.mdLang : lang; + textToCopy = '```' + mdLang + '\n' + rawCode + '\n```'; + } else { + textToCopy = rawCode; + } + + writeClipboard(textToCopy, btn); + }); + }); +} + +function writeClipboard(text, btn) { + navigator.clipboard.writeText(text).then(() => { + flashCopied(btn); + }).catch(() => { + // Fallback for non-HTTPS / older browsers + const ta = document.createElement('textarea'); + ta.value = text; + ta.style.position = 'fixed'; + ta.style.opacity = '0'; + document.body.appendChild(ta); + ta.select(); + document.execCommand('copy'); + document.body.removeChild(ta); + flashCopied(btn); + }); +} + +function flashCopied(btn) { + const original = btn.textContent; + btn.textContent = 'Copied!'; + btn.classList.add('copied'); + setTimeout(() => { + btn.textContent = original; + btn.classList.remove('copied'); + }, 2000); +} + +// ===== Copy Page Button ===== +function injectCopyPageButton(container) { + const header = container.querySelector('.page-header'); + if (!header) return; + + // Don't double-inject + if (header.querySelector('.copy-page-btn')) return; + + const btn = document.createElement('button'); + btn.className = 'copy-page-btn'; + btn.innerHTML = `Copy page`; + btn.addEventListener('click', () => { + const article = container.querySelector('article.page'); + if (!article) return; + const md = pageToMarkdown(article); + writeClipboard(md, btn.querySelector('span')); + }); + + header.appendChild(btn); +} + +// ===== HTML-to-Markdown Converter ===== +function pageToMarkdown(article) { + const lines = []; + const children = article.children; + + for (const node of children) { + convertNode(node, lines); + } + + return lines.join('\n').replace(/\n{3,}/g, '\n\n').trim() + '\n'; +} + +function convertNode(el, lines) { + const tag = el.tagName; + + // Skip non-content elements + if (el.classList.contains('copy-page-btn')) return; + if (el.classList.contains('copy-actions')) return; + + // Page header block + if (el.classList.contains('page-header')) { + const h1 = el.querySelector('h1'); + const subtitle = el.querySelector('.page-subtitle'); + if (h1) lines.push('# ' + h1.textContent.trim(), ''); + if (subtitle) lines.push('> ' + subtitle.textContent.trim(), ''); + return; + } + + // Headings + if (/^H[1-6]$/.test(tag)) { + const level = parseInt(tag[1]); + lines.push('', '#'.repeat(level) + ' ' + el.textContent.trim(), ''); + return; + } + + // Callouts + if (el.classList.contains('callout')) { + const content = el.querySelector('.callout-content'); + if (content) { + lines.push('', '> ' + inlineText(content), ''); + } + return; + } + + // Code blocks + if (el.classList.contains('code-block')) { + const code = el.querySelector('code'); + const lang = el.dataset.lang || ''; + const mdLang = el.hasAttribute('data-md-lang') ? el.dataset.mdLang : lang; + lines.push('', '```' + mdLang); + lines.push(code.textContent); + lines.push('```', ''); + return; + } + + // Diagrams + if (el.classList.contains('diagram-container')) { + const pre = el.querySelector('pre'); + if (pre) { + lines.push('', '```'); + lines.push(pre.textContent); + lines.push('```', ''); + } + return; + } + + // Tables + if (tag === 'TABLE') { + lines.push(''); + const rows = el.querySelectorAll('tr'); + rows.forEach((row, i) => { + const cells = row.querySelectorAll('th, td'); + const cellTexts = Array.from(cells).map(c => inlineText(c)); + lines.push('| ' + cellTexts.join(' | ') + ' |'); + if (i === 0) { + lines.push('| ' + cellTexts.map(() => '---').join(' | ') + ' |'); + } + }); + lines.push(''); + return; + } + + // Paragraphs + if (tag === 'P') { + lines.push(inlineText(el), ''); + return; + } + + // Unordered lists + if (tag === 'UL') { + const items = el.querySelectorAll(':scope > li'); + items.forEach(li => { + lines.push('- ' + inlineText(li)); + }); + lines.push(''); + return; + } + + // Ordered lists + if (tag === 'OL') { + const items = el.querySelectorAll(':scope > li'); + items.forEach((li, i) => { + lines.push((i + 1) + '. ' + inlineText(li)); + }); + lines.push(''); + return; + } + + // Feature grid + if (el.classList.contains('feature-grid')) { + const cards = el.querySelectorAll('.feature-card'); + cards.forEach(card => { + const h3 = card.querySelector('h3'); + const p = card.querySelector('p'); + if (h3) lines.push('### ' + h3.textContent.trim()); + if (p) lines.push(p.textContent.trim(), ''); + }); + return; + } + + // Two-column layout + if (el.classList.contains('two-col')) { + for (const child of el.children) { + for (const inner of child.children) { + convertNode(inner, lines); + } + } + return; + } + + // Phase cards + if (el.classList.contains('phase-card')) { + const header = el.querySelector('.phase-header'); + if (header) lines.push('', '**' + header.textContent.trim() + '**'); + const ul = el.querySelector('ul'); + if (ul) convertNode(ul, lines); + return; + } + + // Accordion / details + if (tag === 'DETAILS') { + const summary = el.querySelector('summary'); + const content = el.querySelector('.accordion-content'); + if (summary) lines.push('', '**' + summary.textContent.trim() + '**'); + if (content) { + for (const child of content.children) { + convertNode(child, lines); + } + } + return; + } + + // Generic container — recurse (div, section, nav, etc.) + if (el.children && el.children.length > 0) { + for (const child of el.children) { + convertNode(child, lines); + } + return; + } +} + +function inlineText(el) { + let result = ''; + for (const node of el.childNodes) { + if (node.nodeType === Node.TEXT_NODE) { + result += node.textContent; + } else if (node.nodeType === Node.ELEMENT_NODE) { + const tag = node.tagName; + // Skip copy buttons + if (node.classList.contains('copy-actions') || node.classList.contains('copy-btn') || node.classList.contains('copy-page-btn')) continue; + + if (tag === 'STRONG' || tag === 'B') { + result += '**' + inlineText(node) + '**'; + } else if (tag === 'EM' || tag === 'I') { + result += '*' + inlineText(node) + '*'; + } else if (tag === 'CODE') { + result += '`' + node.textContent + '`'; + } else if (tag === 'A') { + const href = node.getAttribute('href') || ''; + result += '[' + inlineText(node) + '](' + href + ')'; + } else if (tag === 'SPAN' && node.classList.contains('badge')) { + result += node.textContent.trim(); + } else if (tag === 'SPAN' && node.classList.contains('direction')) { + result += ' ' + node.textContent.trim(); + } else { + result += inlineText(node); + } + } + } + return result.replace(/\s+/g, ' ').trim(); +} + +// ===== Event Listeners ===== + +// Nav items +document.querySelectorAll('.nav-item').forEach(item => { + item.addEventListener('click', (e) => { + e.preventDefault(); + navigateTo(item.dataset.page); + history.pushState(null, '', '#' + item.dataset.page); + }); +}); + +// Footer nav +document.getElementById('footerPrev').addEventListener('click', (e) => { + e.preventDefault(); + if (currentPageIndex > 0) { + const prev = pages[currentPageIndex - 1]; + navigateTo(prev.id); + history.pushState(null, '', '#' + prev.id); + } +}); + +document.getElementById('footerNext').addEventListener('click', (e) => { + e.preventDefault(); + if (currentPageIndex < pages.length - 1) { + const next = pages[currentPageIndex + 1]; + navigateTo(next.id); + history.pushState(null, '', '#' + next.id); + } +}); + +// In-page anchor links (delegated) +document.addEventListener('click', (e) => { + const link = e.target.closest('a[href^="#"]'); + if (link && !link.classList.contains('nav-item') && !link.classList.contains('footer-prev') && !link.classList.contains('footer-next')) { + const target = link.getAttribute('href').slice(1); + const page = pages.find(p => p.id === target); + if (page) { + e.preventDefault(); + navigateTo(target); + history.pushState(null, '', '#' + target); + } + } +}); + +// Hash change (browser back/forward) +window.addEventListener('hashchange', () => { + const hash = window.location.hash.slice(1) || 'overview'; + navigateTo(hash); +}); + +// ===== Mobile Sidebar ===== +const sidebarToggle = document.getElementById('sidebarToggle'); +const sidebar = document.getElementById('sidebar'); +const sidebarOverlay = document.getElementById('sidebarOverlay'); + +function openSidebar() { + sidebar.classList.add('open'); + sidebarOverlay.classList.add('visible'); +} + +function closeSidebar() { + sidebar.classList.remove('open'); + sidebarOverlay.classList.remove('visible'); +} + +sidebarToggle.addEventListener('click', () => { + sidebar.classList.contains('open') ? closeSidebar() : openSidebar(); +}); + +sidebarOverlay.addEventListener('click', closeSidebar); + +// ===== Search ===== +const searchBar = document.getElementById('searchBar'); +const searchModal = document.getElementById('searchModal'); +const searchModalInput = document.getElementById('searchModalInput'); +const searchResults = document.getElementById('searchResults'); + +function openSearch() { + searchModal.style.display = 'flex'; + searchModalInput.value = ''; + searchModalInput.focus(); + renderSearchResults(''); +} + +function closeSearch() { + searchModal.style.display = 'none'; +} + +function renderSearchResults(query) { + if (!query.trim()) { + searchResults.innerHTML = pages.map(p => + `
+
${p.section}
+
${p.title}
+
` + ).join(''); + return; + } + + const q = query.toLowerCase().trim(); + const results = pages.filter(p => + p.title.toLowerCase().includes(q) || (searchIndex[p.id] && searchIndex[p.id].includes(q)) + ); + + if (results.length === 0) { + searchResults.innerHTML = '
No results found
'; + return; + } + + searchResults.innerHTML = results.map(p => + ` +
${p.section}
+
${p.title}
+
` + ).join(''); +} + +searchBar.addEventListener('click', openSearch); + +searchModal.querySelector('.search-modal-overlay').addEventListener('click', closeSearch); + +searchModalInput.addEventListener('input', (e) => { + renderSearchResults(e.target.value); +}); + +searchResults.addEventListener('click', (e) => { + const item = e.target.closest('.search-result-item'); + if (item) { + e.preventDefault(); + const pageId = item.dataset.page; + closeSearch(); + navigateTo(pageId); + history.pushState(null, '', '#' + pageId); + } +}); + +// Keyboard shortcuts +document.addEventListener('keydown', (e) => { + // Ctrl+K / Cmd+K to toggle search + if ((e.ctrlKey || e.metaKey) && e.key === 'k') { + e.preventDefault(); + searchModal.style.display === 'flex' ? closeSearch() : openSearch(); + } + + // Escape to close search + if (e.key === 'Escape' && searchModal.style.display === 'flex') { + closeSearch(); + } + + // Arrow nav in search results + if (searchModal.style.display === 'flex') { + const items = searchResults.querySelectorAll('.search-result-item'); + const active = searchResults.querySelector('.search-result-item.active'); + let idx = Array.from(items).indexOf(active); + + if (e.key === 'ArrowDown') { + e.preventDefault(); + if (active) active.classList.remove('active'); + idx = (idx + 1) % items.length; + items[idx].classList.add('active'); + items[idx].scrollIntoView({ block: 'nearest' }); + } else if (e.key === 'ArrowUp') { + e.preventDefault(); + if (active) active.classList.remove('active'); + idx = idx <= 0 ? items.length - 1 : idx - 1; + items[idx].classList.add('active'); + items[idx].scrollIntoView({ block: 'nearest' }); + } else if (e.key === 'Enter') { + if (active) { + e.preventDefault(); + const pageId = active.dataset.page; + closeSearch(); + navigateTo(pageId); + history.pushState(null, '', '#' + pageId); + } + } + } +}); + +// ===== Init ===== +(async () => { + const initialHash = window.location.hash.slice(1) || 'overview'; + await navigateTo(initialHash); + // Pre-fetch remaining pages in the background for search + buildSearchIndex(); +})(); diff --git a/docs-site/assets/logo.svg b/docs-site/assets/logo.svg new file mode 100644 index 0000000..398cc6a --- /dev/null +++ b/docs-site/assets/logo.svg @@ -0,0 +1,21 @@ + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/docs-site/index.html b/docs-site/index.html new file mode 100644 index 0000000..8cebcdd --- /dev/null +++ b/docs-site/index.html @@ -0,0 +1,119 @@ + + + + + + ReCursor Documentation + + + + + + + + +
+
+ +
+ + GitHub +
+
+
+ +
+ + + + + + + +
+
+ +
+
+
+
+ + + +
+
+ + + + + + + diff --git a/docs-site/pages/agent-sdk.html b/docs-site/pages/agent-sdk.html new file mode 100644 index 0000000..516560c --- /dev/null +++ b/docs-site/pages/agent-sdk.html @@ -0,0 +1,111 @@ +
+ + +

When to Use

+ + + + + + + + +
ScenarioSolution
Chat with agent from mobileAgent SDK session
Approve tool calls from mobileHooks + Agent SDK
See what Claude Code is doingHooks
Control existing Claude Code sessionNot supported
+ +

Setup

+
+
Terminal
+
npm install @anthropic-ai/claude-agent-sdk
+
+ +

Basic Session

+
+
TypeScript
+
import { Agent } from '@anthropic-ai/claude-agent-sdk';
+import { ReadTool, EditTool, BashTool } from '@anthropic-ai/claude-agent-sdk/tools';
+
+const agent = new Agent({
+  model: 'claude-3-5-sonnet-20241022',
+  tools: [new ReadTool(), new EditTool(), new BashTool()],
+  workingDirectory: '/home/user/project',
+});
+
+const response = await agent.run({
+  messages: [{ role: 'user', content: 'Refactor the auth module' }],
+});
+
+ +

Bridge Integration

+
+
TypeScript
+
class AgentSessionManager {
+  private sessions: Map<string, Agent> = new Map();
+
+  async createSession(sessionId: string, config: SessionConfig) {
+    const agent = new Agent({
+      model: config.model || 'claude-3-5-sonnet-20241022',
+      tools: this.loadTools(config.toolAllowlist),
+      workingDirectory: config.workingDirectory,
+    });
+
+    this.sessions.set(sessionId, agent);
+
+    agent.on('tool_use', (event) => {
+      this.eventEmitter.emit('tool-use', { sessionId, event });
+    });
+  }
+
+  async sendMessage(sessionId: string, message: string) {
+    const agent = this.sessions.get(sessionId);
+    const stream = agent.run({
+      messages: [{ role: 'user', content: message }],
+    });
+    for await (const chunk of stream) {
+      this.eventEmitter.emit('stream_chunk', { sessionId, chunk });
+    }
+  }
+}
+
+ +

Tool Configuration

+
+
TypeScript
+
import {
+  ReadTool, EditTool, BashTool,
+  GlobTool, GrepTool, LSTool,
+} from '@anthropic-ai/claude-agent-sdk/tools';
+
+const tools = [
+  new ReadTool(),      // Read file contents
+  new EditTool(),      // Edit files (find/replace)
+  new BashTool({       // Execute shell commands
+    allowedCommands: ['git', 'flutter', 'npm'],
+  }),
+  new GlobTool(),      // File globbing
+  new GrepTool(),      // Text search
+  new LSTool(),        // List directory contents
+];
+
+ +

Error Handling

+ + + + + + + + +
ErrorCauseSolution
APIErrorInvalid API key or rate limitCheck API key, implement backoff
ToolErrorTool execution failedShow error in tool card
TimeoutErrorTool took too longSet appropriate timeouts
SessionErrorSession ID not foundValidate session on mobile
+ +

Security

+
    +
  • API Key Management — Store ANTHROPIC_API_KEY in bridge server environment only. Never expose to mobile app.
  • +
  • Tool Restrictions — Use allowlists for permitted commands and blocklists for dangerous operations.
  • +
  • Working Directory Isolation — Verify working directories are within allowed paths.
  • +
+
diff --git a/docs-site/pages/architecture.html b/docs-site/pages/architecture.html new file mode 100644 index 0000000..521ab88 --- /dev/null +++ b/docs-site/pages/architecture.html @@ -0,0 +1,143 @@ +
+ + +

System Context

+
+
+  +---------------------------+
+  |   ReCursor Flutter App    |
+  |  +---------------------+  |
+  |  | OpenCode-like UI    |  |
+  |  | Riverpod State Mgmt |  |
+  |  | WebSocket Client    |  |
+  |  +----------+----------+  |
+  +-------------|-------------+
+                | wss:// (Tailscale/WireGuard)
+  +-------------|-----------------------------+
+  |  Development Machine                      |
+  |  +--------v----------+                    |
+  |  | Bridge Server     |                    |
+  |  | (TypeScript/Node)  |                    |
+  |  +--+----------+-----+                    |
+  |     |          |                           |
+  |  +--v---+  +---v-----------+              |
+  |  | Hooks|  | Agent SDK     |              |
+  |  +--+---+  | (Parallel)    |              |
+  |     |      +-------+-------+              |
+  |  +--v-----------+  |                      |
+  |  | Claude Code  |  +---> Anthropic API    |
+  |  | CLI          |                          |
+  |  +--------------+                          |
+  +--------------------------------------------+
+
+ +

Key Architectural Decisions

+ +

1. Claude Code Integration Strategy

+

Selected Architecture: Hybrid approach using Hooks for event observation + Agent SDK for parallel sessions.

+ + + + + + + + +
ApproachStatusNotes
Direct Remote Control ProtocolNot AvailableFirst-party only. No public API for third-party clients.
Claude Code HooksSupportedHTTP-based event observation (one-way)
Agent SDKSupportedParallel agent sessions (not mirroring)
MCPSupportedTool interoperability
+ +

2. UI/UX Pattern

+

ReCursor adopts OpenCode's UI patterns for the mobile interface:

+
    +
  • Tool Cards — Rich, interactive cards for tool use and results
  • +
  • Diff Viewer — Syntax-highlighted unified/side-by-side diffs
  • +
  • Session Timeline — Visual timeline of agent actions and decisions
  • +
  • Chat Interface — Streaming text with markdown rendering
  • +
+ +

3. Communication Pattern

+
+
Communication Flow
+
Mobile App <--WebSocket--> Bridge Server <--HTTP--> Claude Code Hooks
+     |                                              |
+     |                                              v
+     +------------------------------------------Observes Events
+
+
    +
  • WebSocket — Bidirectional, real-time communication between mobile and bridge
  • +
  • HTTP Hooks — One-way event streaming from Claude Code to bridge
  • +
  • No Direct Mobile-to-Claude-Code — All communication flows through the bridge
  • +
+ +

Component Responsibilities

+

ReCursor Flutter App

+ + + + + + + + +
ComponentResponsibility
UI LayerRender OpenCode-style tool cards, diff viewer, timeline
State ManagementRiverpod providers for sessions, messages, connection
WebSocket ClientConnect to bridge, handle reconnections, heartbeat
Local StorageDrift for persistence, Hive for caching
+ +

Bridge Server

+ + + + + + + + +
ComponentResponsibility
WebSocket ServerAccept mobile connections, manage sessions
Event QueueBuffer events from Hooks, replay on reconnect
HTTP EndpointReceive events from Claude Code Hooks
Agent SDK AdapterOptional parallel session management
+ +

Security Model

+
+
+  Mobile  --->  WireGuard/Tailscale  --->  TLS 1.3  --->  Device Token  --->  Bridge
+           (Network Layer)          (Transport)       (Application)
+
+
    +
  1. Network Layer: Tailscale/WireGuard mesh VPN
  2. +
  3. Transport Layer: WSS (WebSocket Secure) with TLS 1.3
  4. +
  5. Application Layer: Device pairing token on WebSocket handshake (no user accounts)
  6. +
+ +

Data Flow Summary

+
+
+

Outbound (Mobile to Agent)

+
    +
  1. User sends message from mobile app
  2. +
  3. Message queued locally (if offline)
  4. +
  5. WebSocket transmits to bridge
  6. +
  7. Bridge forwards to Agent SDK session
  8. +
  9. Agent SDK calls Claude API
  10. +
+
+
+

Inbound (Agent to Mobile)

+
    +
  1. Claude Code executes tool/action
  2. +
  3. Hooks POST event to bridge
  4. +
  5. Bridge queues event (if mobile disconnected)
  6. +
  7. WebSocket transmits to mobile
  8. +
  9. UI renders OpenCode-style component
  10. +
+
+
+ +

Limitations & Constraints

+ + + + + + + +
ConstraintImpactMitigation
Hooks are one-wayCannot inject messages into Claude CodeUse Agent SDK for parallel session
No session mirroringMobile sees events but not full contextHooks include rich event metadata
Requires local Claude CodeCannot work without desktop agentClear user messaging, offline queue
+
diff --git a/docs-site/pages/bridge-protocol.html b/docs-site/pages/bridge-protocol.html new file mode 100644 index 0000000..f25a877 --- /dev/null +++ b/docs-site/pages/bridge-protocol.html @@ -0,0 +1,208 @@ +
+ + +

Connection Lifecycle

+
+
+  ReCursor App        Bridge Server        Claude Code Hooks     Claude Code
+      |                    |                      |                   |
+      |--- wss:// + token ->                      |                   |
+      |<-- connection_ack --|                      |                   |
+      |                    |                      |                   |
+      |-- heartbeat_ping ->|                      |                   |
+      |<-- heartbeat_pong --|                      |                   |
+      |                    |                      |<-- SessionStart --|
+      |                    |<-- HTTP POST ---------|                   |
+      |<-- session_started -|                      |                   |
+
+ +

Message Format

+

All messages are JSON objects with a type field and optional id for request-response correlation.

+
+
JSON
+
{
+  "type": "message_type",
+  "id": "unique-msg-id",
+  "timestamp": "2026-03-16T10:32:00Z",
+  "payload": { ... }
+}
+
+ +

Message Types

+ +

Connection

+ +

auth (client → server)

+

Sent immediately after WebSocket opens for device pairing authentication.

+
+
JSON
+
{
+  "type": "auth",
+  "id": "auth-001",
+  "payload": {
+    "token": "device-pairing-token-xxxxx",
+    "client_version": "1.0.0",
+    "platform": "ios"
+  }
+}
+
+ +

connection_ack (server → client)

+

Confirms authentication and connection.

+
+
JSON
+
{
+  "type": "connection_ack",
+  "id": "auth-001",
+  "payload": {
+    "server_version": "1.0.0",
+    "supported_agents": ["claude-code", "opencode", "aider", "goose"],
+    "active_sessions": [
+      { "session_id": "sess-abc", "agent": "claude-code", "title": "Bridge startup validation" }
+    ]
+  }
+}
+
+ +

heartbeat_ping / heartbeat_pong

+

Keep-alive messages. Client sends ping, server responds with pong. Interval: 15 seconds. If no pong within 10 seconds, client triggers reconnect.

+ +

Agent Sessions

+

session_start (client → server)

+
+
JSON
+
{
+  "type": "session_start",
+  "id": "req-001",
+  "payload": {
+    "agent": "claude-code",
+    "session_id": null,
+    "working_directory": "/home/user/project",
+    "resume": false
+  }
+}
+
+ +

session_ready (server → client)

+
+
JSON
+
{
+  "type": "session_ready",
+  "id": "req-001",
+  "payload": {
+    "session_id": "sess-abc123",
+    "agent": "claude-code",
+    "working_directory": "/home/user/project",
+    "branch": "main",
+    "status": "ready"
+  }
+}
+
+ +

Chat Messages

+

message (client → server)

+
+
JSON
+
{
+  "type": "message",
+  "id": "msg-001",
+  "payload": {
+    "session_id": "sess-abc123",
+    "content": "Tighten the bridge startup validation",
+    "role": "user"
+  }
+}
+
+ +

stream_chunk (server → client)

+
+
JSON
+
{
+  "type": "stream_chunk",
+  "payload": {
+    "session_id": "sess-abc123",
+    "message_id": "msg-resp-001",
+    "content": "I'll tighten the bridge startup validation",
+    "is_tool_use": false
+  }
+}
+
+ +

Tool Calls

+

tool_call (server → client)

+
+
JSON
+
{
+  "type": "tool_call",
+  "id": "tool-001",
+  "payload": {
+    "session_id": "sess-abc123",
+    "tool_call_id": "call-abc123",
+    "tool": "edit_file",
+    "params": {
+      "file_path": "/home/user/project/lib/main.dart",
+      "old_string": "return wsAllowed(url);",
+      "new_string": "return requireWss(url);"
+    },
+    "description": "Require secure bridge URLs"
+  }
+}
+
+ +

approval_required (server → client)

+
+
JSON
+
{
+  "type": "approval_required",
+  "id": "tool-001",
+  "payload": {
+    "session_id": "sess-abc123",
+    "tool_call_id": "call-abc123",
+    "tool": "run_command",
+    "params": { "command": "flutter build apk" },
+    "description": "Build Android APK",
+    "risk_level": "medium",
+    "source": "hooks"
+  }
+}
+
+ +

approval_response (client → server)

+
+
JSON
+
{
+  "type": "approval_response",
+  "id": "tool-001",
+  "payload": {
+    "session_id": "sess-abc123",
+    "tool_call_id": "call-abc123",
+    "decision": "approved"
+  }
+}
+
+ +

Error Codes

+ + + + + + + + + + +
CodeDescriptionRecoverable
AUTH_FAILEDInvalid or expired tokenNo
SESSION_NOT_FOUNDSession ID doesn't existNo
AGENT_ERRORAgent execution failedYes
TOOL_ERRORTool execution failedYes
GIT_ERRORGit operation failedYes
RATE_LIMITEDToo many requestsYes
+ +

Reconnection Behavior

+
    +
  1. Client sends auth message
  2. +
  3. Server responds with connection_ack including active_sessions
  4. +
  5. Server replays any queued events (notifications, tool results)
  6. +
  7. Client acknowledges with notification_ack
  8. +
+
diff --git a/docs-site/pages/data-flow.html b/docs-site/pages/data-flow.html new file mode 100644 index 0000000..d3a7c25 --- /dev/null +++ b/docs-site/pages/data-flow.html @@ -0,0 +1,67 @@ +
+ + +

User Sends a Message

+
+
+  ReCursor App       Bridge Server       Agent SDK         Claude API
+      |                    |                 |                  |
+      |--- message ------->|                 |                  |
+      |                    |-- agent.run() ->|                  |
+      |                    |                 |--- API request ->|
+      |                    |                 |<-- stream -------|
+      |                    |<- stream_chunk -|                  |
+      |<-- stream_chunk ---|                 |                  |
+      |    (update UI)     |                 |                  |
+      |                    |<- complete -----|                  |
+      |<-- stream_end -----|                 |                  |
+
+ +

Tool Execution with Approval

+
+
+  ReCursor App       Bridge Server       Agent SDK         Tools
+      |                    |                 |               |
+      |                    |                 |-- tool_use -->|
+      |                    |<- tool_use -----|               |
+      |<-- approval_req ---|                 |               |
+      |                    |                 |               |
+      |-- approved ------->|                 |               |
+      |                    |-- continue ---->|               |
+      |                    |                 |-- execute --->|
+      |                    |                 |<-- result ----|
+      |                    |<- tool_result --|               |
+      |<-- tool_result ----|                 |               |
+      |  (render card)     |                 |               |
+
+ +

Hook Event Observation

+
+
+  ReCursor App       Bridge Server        Hooks          Claude Code
+      |                    |                 |               |
+      |                    |                 |<- PostToolUse-|
+      |                    |<- HTTP POST ----|               |
+      |                    |--- 200 OK ----->|               |
+      |<-- claude_event ---|                 |               |
+      |  (update timeline) |                 |               |
+
+ +

Reconnection & Event Replay

+
+
+  ReCursor App       Bridge Server       Event Queue
+      |                    |                 |
+      |  (disconnected)    |                 |
+      |                    |<- events -------|  (queued while offline)
+      |                    |                 |
+      |--- auth ---------> |                 |
+      |<-- connection_ack -|                 |
+      |<-- queued events --|-- dequeue ----->|
+      |-- notification_ack>|                 |
+
+
diff --git a/docs-site/pages/hooks.html b/docs-site/pages/hooks.html new file mode 100644 index 0000000..9e259d7 --- /dev/null +++ b/docs-site/pages/hooks.html @@ -0,0 +1,150 @@ +
+ + +
+
+ +
+
+ Hooks are one-way observation only. They cannot inject messages or control the Claude Code session. For bidirectional communication, use the Agent SDK. +
+
+ +

Supported Hook Events

+ + + + + + + + + + + + +
EventTriggerPayload
SessionStartNew Claude Code session beginsSession metadata
SessionEndSession terminatesSession summary
PreToolUseAgent about to use a toolTool, params, risk level
PostToolUseTool execution completedTool, result, metadata
UserPromptSubmitUser submits a promptPrompt text, context
StopAgent stops executionStop reason, context
SubagentStopSubagent stops executionSubagent result, context
NotificationSystem notificationMessage, level
+ +

Hook Configuration

+

Hooks are configured via hooks.json in your Claude Code plugin directory. Two types are supported:

+
    +
  • type: "command" — Execute bash commands for deterministic checks
  • +
  • type: "prompt" — Use LLM-driven decision making
  • +
+ +

Command Hooks (Recommended)

+
+
hooks.json
+
{
+  "description": "ReCursor bridge integration",
+  "hooks": {
+    "PreToolUse": [{
+      "hooks": [{
+        "type": "command",
+        "command": "curl -X POST https://100.78.42.15:3000/hooks/event -H 'Content-Type: application/json' -H 'Authorization: Bearer $BRIDGE_TOKEN' -d @-",
+        "timeout": 10
+      }]
+    }],
+    "PostToolUse": [{
+      "hooks": [{
+        "type": "command",
+        "command": "curl -X POST https://100.78.42.15:3000/hooks/event -H 'Content-Type: application/json' -H 'Authorization: Bearer $BRIDGE_TOKEN' -d @-",
+        "timeout": 10
+      }]
+    }],
+    "SessionStart": [{
+      "hooks": [{
+        "type": "command",
+        "command": "curl -X POST https://100.78.42.15:3000/hooks/event -H 'Content-Type: application/json' -H 'Authorization: Bearer $BRIDGE_TOKEN' -d @-",
+        "timeout": 10
+      }]
+    }]
+  }
+}
+
+ +

Plugin Directory Structure

+
+
File Tree
+
~/.claude-code/plugins/
+  recursor-bridge/
+    hooks.json          # Hook definitions
+    README.md           # Plugin documentation
+
+ +

Event Payloads

+ +

PostToolUse

+
+
JSON
+
{
+  "event_type": "PostToolUse",
+  "session_id": "sess-abc123",
+  "timestamp": "2026-03-17T10:32:00Z",
+  "payload": {
+    "tool": "edit_file",
+    "params": {
+      "file_path": "/home/user/project/lib/main.dart",
+      "old_string": "void main() {",
+      "new_string": "void main() async {"
+    },
+    "result": { "success": true, "diff": "..." },
+    "metadata": { "token_count": 150, "duration_ms": 250 }
+  }
+}
+
+ +

PreToolUse

+
+
JSON
+
{
+  "event_type": "PreToolUse",
+  "session_id": "sess-abc123",
+  "timestamp": "2026-03-17T10:32:00Z",
+  "payload": {
+    "tool": "Bash",
+    "params": { "command": "rm -rf /important" },
+    "risk_level": "high",
+    "requires_approval": true
+  }
+}
+
+ +

Security Considerations

+
    +
  1. Token Authentication — Always use Authorization: Bearer <token>
  2. +
  3. HTTPS Only — Use TLS for all hook communications
  4. +
  5. Payload Validation — Validate all incoming hook events before processing
  6. +
  7. Rate Limiting — Implement rate limiting on the /hooks/event endpoint
  8. +
+ +

Troubleshooting

+
+
+ Hooks not firing +
+
    +
  1. Verify hooks.json syntax is valid JSON
  2. +
  3. Check plugin is in correct directory: ~/.claude-code/plugins/
  4. +
  5. Ensure hook commands have execute permissions
  6. +
  7. Review Claude Code logs for hook execution errors
  8. +
+
+
+
+ Bridge not receiving events +
+
    +
  1. Verify bridge URL is accessible from Claude Code host
  2. +
  3. Check firewall rules allow outbound HTTP to bridge
  4. +
  5. Confirm authentication token matches
  6. +
  7. Test with simple curl command manually
  8. +
+
+
+
+
diff --git a/docs-site/pages/offline.html b/docs-site/pages/offline.html new file mode 100644 index 0000000..b473c30 --- /dev/null +++ b/docs-site/pages/offline.html @@ -0,0 +1,91 @@ +
+ + +

Storage Strategy

+ + + + + + + +
Data TypeStorageRationale
Conversations, tasks, agent configsDrift (SQLite)Type-safe queries, migrations, reactive streams
UI preferences, cached tokens, session stateHiveFast key-value for ephemeral data
File content cacheFile systemLarge blobs don't belong in SQLite
+ +

Repository Pattern

+
+
Architecture
+
UI Layer (Riverpod providers)
+    |
+Repository Layer (abstracts local vs. remote)
+    |
+    +-- Local Data Source (Drift / Hive)
+    +-- Remote Data Source (Bridge WebSocket)
+
+

Repository reads from local DB first (instant UI response), fetches from bridge in background, and Drift's reactive queries automatically update the UI when local data changes.

+ +

Sync Queue

+

When offline, mutations go into a local queue:

+
+
Dart
+
class SyncQueue extends Table {
+  IntColumn get id => integer().autoIncrement()();
+  TextColumn get operation => text()();     // "send_message", "approve_tool"
+  TextColumn get payload => text()();       // JSON: full operation
+  TextColumn get sessionId => text().nullable()();
+  DateTimeColumn get createdAt => dateTime()();
+  BoolColumn get synced => boolean().withDefault(const Constant(false))();
+  IntColumn get retryCount => integer().withDefault(const Constant(0))();
+}
+
+ +

Connection States

+ + + + + + + +
StateDescriptionBehavior
onlineConnected to bridgeSync queue, real-time updates
offlineNo connectivityQueue mutations locally
bridge_unreachableNetwork but no bridgeRetry with backoff, queue mutations
+ +

Sync Strategies

+
+
+

Push-First (Outbound)

+
    +
  1. User action (send message, approve tool)
  2. +
  3. Save to local DB
  4. +
  5. Try to send via WebSocket
  6. +
  7. If failed, add to SyncQueue
  8. +
  9. Show "pending" state in UI
  10. +
+
+
+

Pull-First (Inbound)

+
    +
  1. On reconnect, request events since last sync
  2. +
  3. Merge with local state
  4. +
  5. Resolve conflicts
  6. +
  7. Update UI
  8. +
+
+
+ +

Conflict Resolution

+

Default: Last-write-wins using updated_at timestamps. For destructive operations (git push, file overwrite), the user is prompted with a conflict dialog.

+ +

Storage Limits

+ + + + + + + + +
Data TypeMax SizeCleanup Strategy
SyncQueue1000 itemsFIFO eviction
Messages30 daysArchive to file
Sessions90 daysSoft delete
File cache100 MBLRU eviction
+
diff --git a/docs-site/pages/overview.html b/docs-site/pages/overview.html new file mode 100644 index 0000000..dad3260 --- /dev/null +++ b/docs-site/pages/overview.html @@ -0,0 +1,115 @@ +
+ + +
+
+ +
+
+ Status: Architecture specification complete. Implementation pending. +
+
+ +

ReCursor enables developers to leverage AI-powered coding agents from anywhere, without requiring a desktop environment. Full agentic coding workflows on mobile — plan, code, test, and deploy applications using only your phone or tablet.

+ +

The UI/UX mirrors OpenCode (terminal-native AI coding agent) with its rich tool cards, diff viewer, and session timeline, while the underlying events come from Claude Code running on your development machine via supported integration mechanisms.

+ +

Why ReCursor?

+
+
+
📱
+

Coding On-the-Go

+

Review code, approve changes, and chat with agents from anywhere on your mobile device.

+
+
+
🚀
+

Remote Productivity

+

No laptop required for code review, simple fixes, and agent interactions.

+
+
+
🤖
+

AI-First Workflow

+

Voice commands to AI agents while away from your desk. Full agent control from mobile.

+
+
+
🔄
+

Continuous Context

+

Start coding at your desk, continue from your phone. Seamless session handoff.

+
+
+ +

How It Works

+
+
+  +-----------------------+        +-------------------------------+
+  |  Mobile Device        |        |  Development Machine          |
+  |                       |        |                               |
+  |  +--ReCursor App---+  |        |  +--Bridge Server----------+  |
+  |  | OpenCode-style  |  |  WSS   |  | WebSocket + HTTP        |  |
+  |  | UI (Tool Cards, |<-------->|  | Event Queue             |  |
+  |  | Diff Viewer,    |  | Tunnel |  | Agent SDK Adapter       |  |
+  |  | Timeline)       |  |        |  +-----------+-------------+  |
+  |  +-----------------+  |        |              |                 |
+  +-----------------------+        |   +----------v-----------+    |
+                                   |   | Claude Code Hooks    |    |
+                                   |   | (Event Observer)     |    |
+                                   |   +----------+-----------+    |
+                                   |              |                 |
+                                   |   +----------v-----------+    |
+                                   |   | Claude Code CLI      |    |
+                                   |   +----------------------+    |
+                                   +-------------------------------+
+
+ +

Integration Strategy

+ + + + + + + + + + +
ApproachStatusNotes
Direct Remote ControlNot AvailableFirst-party only (claude.ai/code, official apps)
Claude Code HooksSupportedHTTP-based event observation (one-way)
Agent SDKSupportedParallel agent sessions (not mirroring)
MCP (Model Context Protocol)SupportedTool interoperability
+ +
+
+ +
+
+ Important: Claude Code Remote Control is designed exclusively for first-party Anthropic clients. ReCursor does not claim to mirror or control existing Claude Code sessions. +
+
+ +

Core Features

+ + + + + + + + + + + + + + +
FeatureDescriptionPhase
Agent Chat InterfaceMobile chat UI with OpenCode-style tool cardsPhase 1
Tool Call ApprovalApprove/reject agent actions with rich contextPhase 1
Code Diff ViewerSyntax-highlighted diffs with OpenCode patternsPhase 2
Git OperationsCommit, push, pull, merge from mobilePhase 2
Session TimelineVisual timeline of agent actions and decisionsPhase 2
Push NotificationsReal-time alerts for agent events via WebSocketPhase 2
Voice CommandsSpeech-to-code capabilitiesPhase 3
Offline ModeWork without connectivity, sync on reconnectPhase 3
+ +

Next Steps

+ +
diff --git a/docs-site/pages/quickstart.html b/docs-site/pages/quickstart.html new file mode 100644 index 0000000..ac79ce3 --- /dev/null +++ b/docs-site/pages/quickstart.html @@ -0,0 +1,76 @@ +
+ + +
+
+ +
+
+ Prerequisites: Node.js 20+, Flutter 3.x, Claude Code CLI installed, and an Anthropic API key. +
+
+ +

Step 1: Start the Bridge Server

+

The bridge server runs on your development machine and relays events between Claude Code and the mobile app.

+
+
Terminal
+
cd packages/bridge
+npm install
+cp .env.example .env   # Add your ANTHROPIC_API_KEY
+npm run dev
+
+ +

Step 2: Configure Claude Code Hooks

+

Set up Claude Code to forward events to the bridge.

+
+
~/.claude-code/plugins/recursor-bridge/hooks.json
+
{
+  "description": "ReCursor bridge integration",
+  "hooks": {
+    "PostToolUse": [{
+      "hooks": [{
+        "type": "command",
+        "command": "curl -X POST https://localhost:3000/hooks/event -H 'Content-Type: application/json' -H 'Authorization: Bearer $BRIDGE_TOKEN' -d @-",
+        "timeout": 10
+      }]
+    }]
+  }
+}
+
+ +

Step 3: Install the Mobile App

+
+
Terminal
+
cd apps/mobile
+flutter pub get
+flutter run
+
+ +

Step 4: Pair Your Device

+
    +
  1. Open the ReCursor app on your mobile device
  2. +
  3. The app opens directly to bridge pairing (no login required)
  4. +
  5. Scan the QR code displayed by the bridge server
  6. +
  7. The app connects and restores any active sessions
  8. +
+ +
+
+ +
+
+ Remote access: For access outside your local network, set up Tailscale or WireGuard for secure tunneling to your bridge. +
+
+ +

What's Next?

+ +
diff --git a/docs-site/pages/roadmap.html b/docs-site/pages/roadmap.html new file mode 100644 index 0000000..e081952 --- /dev/null +++ b/docs-site/pages/roadmap.html @@ -0,0 +1,80 @@ +
+ + +

Phase 1: Foundation

+
+
+ Phase 1 + Bootable app with bridge connectivity and basic agent chat +
+
    +
  • Initialize Flutter project (iOS + Android)
  • +
  • Bridge connection with QR code pairing
  • +
  • WebSocket client with auto-reconnect
  • +
  • Basic chat interface with streaming text
  • +
  • OpenCode-style message part rendering
  • +
  • Repository file browsing
  • +
  • CI/CD pipeline setup
  • +
+
+ +

Phase 2: Core Features

+
+
+ Phase 2 + Hooks integration, tool cards, diff viewer, notifications +
+
    +
  • Claude Code Hooks event reception
  • +
  • OpenCode-style tool cards (pending/running/completed/error)
  • +
  • Syntax-highlighted diff viewer (unified + side-by-side)
  • +
  • Session timeline with event navigation
  • +
  • Tool call approval flow
  • +
  • WebSocket-based push notifications
  • +
+
+ +

Phase 3: Advanced Features

+
+
+ Phase 3 + Voice, multi-agent, terminal, offline mode +
+
    +
  • Voice commands via platform speech APIs
  • +
  • Multi-agent support (Claude Code, OpenCode, Aider, Goose)
  • +
  • Embedded terminal view with ANSI color rendering
  • +
  • Full offline mode with Drift/Hive sync queue
  • +
+
+ +

Phase 4: Polish & Release

+
+
+ Phase 4 + Performance, accessibility, app store release +
+
    +
  • Large repo handling and performance optimization
  • +
  • Tablet and landscape layouts
  • +
  • Accessibility (TalkBack, VoiceOver, dynamic type)
  • +
  • App Store and Google Play release preparation
  • +
+
+ +

Testing Strategy

+ + + + + + + + + +
LevelToolCoverage
Unitflutter_test + mockitoServices, providers, models
Widgetflutter_testUI components with mocks
GoldenalchemistVisual regression for key screens
Integrationintegration_testFull flows: connect, chat, hooks
E2EpatrolComplete user journeys on real devices
+
diff --git a/docs-site/pages/security.html b/docs-site/pages/security.html new file mode 100644 index 0000000..b135bc1 --- /dev/null +++ b/docs-site/pages/security.html @@ -0,0 +1,101 @@ +
+ + +

Network Layer

+
    +
  • Use a secure tunnel for remote access. Tailscale (recommended) wraps WireGuard encryption, handles NAT traversal, and creates a zero-config mesh VPN.
  • +
  • Always use wss:// — TLS at the application layer + tunnel encryption = defense in depth.
  • +
  • Never expose the bridge on a public IP without tunnel protection.
  • +
+ +

Token Management

+ + + + + + +
Token TypePurposeStorage
Device Pairing TokenAuthenticate mobile app to bridgeflutter_secure_storage
Hook TokenAuthenticate Claude Code Hooks to bridgeBridge server env only
+ +

Device Pairing Token

+
    +
  • Generate: 32+ character crypto-safe random string
  • +
  • Mobile storage: Encrypted with flutter_secure_storage (Keychain / EncryptedSharedPreferences)
  • +
  • QR Code: Bridge URL + token encoded for easy pairing
  • +
  • No user accounts — tokens are per-device
  • +
+ +
+
TypeScript
+
import crypto from 'crypto';
+const token = crypto.randomBytes(32).toString('hex'); // 64 chars
+
+ +

Certificate Pinning

+
+
Dart
+
Future<SecurityContext> getSecureContext() async {
+  final context = SecurityContext(withTrustedRoots: false);
+  final cert = await rootBundle.load('assets/certs/bridge.crt');
+  context.setTrustedCertificatesBytes(cert.buffer.asUint8List());
+  return context;
+}
+
+final channel = IOWebSocketChannel.connect(
+  'wss://100.78.42.15:3000',
+  customClient: HttpClient(context: await getSecureContext()),
+);
+
+ +

Bridge Authorization

+
    +
  • Allowlist of permitted operations — e.g., file read yes, rm -rf / no
  • +
  • Working directory boundaries — agent only accesses project directory
  • +
  • Audit logging — log all commands sent through the bridge
  • +
  • Separate bridge auth from agent auth
  • +
+ +
+
TypeScript
+
const ALLOWED_TOOLS = ['read_file', 'edit_file', 'glob', 'grep', 'ls'];
+const BLOCKED_COMMANDS = ['rm -rf /', 'sudo', 'chmod 777'];
+
+ +

Threat Model

+ + + + + + + + + +
ThreatLikelihoodImpactMitigation
Token theftMediumHighSecure storage, rotation, short expiry
Man-in-the-middleLowHighTLS + certificate pinning
Bridge compromiseLowCriticalWorking directory isolation, allowlist
Replay attacksLowMediumTimestamp validation, nonce
Social engineeringMediumMediumOut-of-band confirmation for destructive ops
+ +

Security Checklist

+
+
+

Development

+
    +
  • Never commit secrets to repository
  • +
  • Use .env for local config
  • +
  • Run flutter analyze security lints
  • +
  • Dependency scanning (Snyk or similar)
  • +
+
+
+

Deployment

+
    +
  • Unique bridge auth tokens per device
  • +
  • Enable TLS 1.3 on bridge server
  • +
  • Configure Tailscale ACLs
  • +
  • Enable audit logging
  • +
+
+
+
diff --git a/docs-site/pages/tech-stack.html b/docs-site/pages/tech-stack.html new file mode 100644 index 0000000..1462602 --- /dev/null +++ b/docs-site/pages/tech-stack.html @@ -0,0 +1,82 @@ +
+ + +

Mobile App

+ + + + + + + + + + + +
LayerChoiceRationale
FrameworkFlutterCross-platform, CC Pocket precedent
State ManagementRiverpodType-safe, testable, Conduit pattern
Networkingweb_socket_channelStandard Flutter WebSocket
Local DBDrift (SQLite)Type-safe queries, migrations
CacheHiveFast key-value for ephemeral data
Notificationsflutter_local_notificationsLocal alerts when backgrounded
Code GenFreezedImmutable models with unions
+ +

Bridge Server

+ + + + + + + + + + + + +
LayerChoiceRationale
RuntimeNode.js 20+CC Pocket pattern, broad ecosystem
LanguageTypeScript 5.xType safety for protocol messages
HTTPExpressMinimal, well-understood
WebSocketwsLightweight, production-ready
Agent@anthropic-ai/sdkOfficial Agent SDK
ValidationZodRuntime type checking
Gitsimple-gitGit operations from bridge
TestingJestStandard test framework
+ +

Infrastructure

+ + + + + + + + + +
LayerChoiceRationale
TunnelTailscale / WireGuardZero-config mesh VPN
CI/CDGitHub Actions + FastlaneIndustry standard
iOS SigningFastlane MatchCode signing management
Android SigningKeystoreStandard Android signing
Crash ReportingSentry (planned)Error tracking
+ +

Project Structure

+
+
File Tree
+
ReCursor/
+  apps/mobile/                  # Flutter app (iOS + Android)
+    lib/
+      core/                     # App-wide infrastructure
+        config/                 # Theme, router, app config
+        models/                 # Data models (Freezed)
+        network/                # WebSocket client
+        providers/              # Riverpod providers
+        storage/                # Drift database, Hive, secure storage
+      features/                 # Feature modules
+        startup/                # Bridge pairing and restore
+        chat/                   # Agent chat interface
+        diff/                   # Code diff viewer
+        session/                # Session management
+        git/                    # Git operations
+        approvals/              # Tool call approvals
+        terminal/               # Terminal view
+        settings/               # Settings screen
+      shared/                   # Shared UI components
+
+  packages/bridge/              # TypeScript bridge server
+    src/
+      agents/                   # Agent SDK integration
+      hooks/                    # Claude Code Hooks receiver
+      websocket/                # WebSocket server
+      git/                      # Git operations
+      auth/                     # Token validation
+
+  docs/                         # Project documentation
+
+
diff --git a/docs-site/pages/ui-patterns.html b/docs-site/pages/ui-patterns.html new file mode 100644 index 0000000..0cb57fa --- /dev/null +++ b/docs-site/pages/ui-patterns.html @@ -0,0 +1,102 @@ +
+ + +

Component Mapping

+ + + + + + + + + +
OpenCode ComponentReCursor WidgetFile
BasicToolToolCardlib/features/chat/widgets/tool_card.dart
DiffChangesDiffViewerlib/features/diff/widgets/diff_viewer.dart
SessionTurnSessionTimelinelib/features/session/widgets/session_timeline.dart
MessagePartMessagePartlib/features/chat/widgets/message_part.dart
ChatMessageMessageBubblelib/features/chat/widgets/message_bubble.dart
+ +

Tool Cards

+

OpenCode renders rich tool cards in the terminal. ReCursor adapts these as Flutter Material cards with four states:

+ + + + + + + + +
StateOpenCode (Terminal)ReCursor (Flutter)
PendingSpinner + "Running..."CircularProgressIndicator + pulse animation
RunningLive output streamStreaming text with fade-in
CompletedCheckmark + resultIcons.check_circle + expandable result
ErrorRed X + error detailsIcons.error + error card
+ +

Flutter Implementation

+
+
Dart
+
class ToolCard extends StatelessWidget {
+  final ToolUse tool;
+  final ToolResult? result;
+  final ToolStatus status;
+
+  @override
+  Widget build(BuildContext context) {
+    return Card(
+      elevation: 2,
+      margin: EdgeInsets.symmetric(vertical: 8, horizontal: 16),
+      child: Column(
+        crossAxisAlignment: CrossAxisAlignment.start,
+        children: [
+          _ToolHeader(tool: tool, status: status),
+          _ToolParams(params: tool.params),
+          if (result != null) _ToolResult(result: result),
+        ],
+      ),
+    );
+  }
+}
+
+ +

Diff Viewer

+
+
Dart
+
class DiffViewer extends StatelessWidget {
+  final List<DiffFile> files;
+  final DiffViewMode viewMode;
+
+  @override
+  Widget build(BuildContext context) {
+    return ListView.builder(
+      itemCount: files.length,
+      itemBuilder: (context, index) {
+        return DiffFileCard(file: files[index], viewMode: viewMode);
+      },
+    );
+  }
+}
+
+ +

Theming

+

ReCursor uses an OpenCode-inspired terminal color scheme adapted for Material You.

+ + + + + + + + + + +
ElementColorUsage
Background #1E1E1EApp background
Text #D4D4D4Primary text
Added lines #4EC9B0Diff additions
Removed lines #F44747Diff deletions
Tool header #569CD6Tool card headers
Accent #CE9178Highlights, links
+ +

Responsive Design

+ + + + + + + + + +
Terminal (OpenCode)Mobile (ReCursor)
Fixed-width fontDynamic font sizing
Horizontal scrollingHorizontal swipe gestures
Keyboard shortcutsTouch gestures + FABs
Split panesTab navigation
Mouse hoverLong-press menus
+
diff --git a/docs-site/styles.css b/docs-site/styles.css new file mode 100644 index 0000000..69046f8 --- /dev/null +++ b/docs-site/styles.css @@ -0,0 +1,1144 @@ +/* ===== Reset & Base ===== */ +*, *::before, *::after { + box-sizing: border-box; + margin: 0; + padding: 0; +} + +:root { + --bg-primary: #0f0f10; + --bg-secondary: #18181b; + --bg-tertiary: #1e1e22; + --bg-elevated: #252529; + --bg-hover: #2a2a2f; + + --border-subtle: #27272a; + --border-default: #3f3f46; + --border-strong: #52525b; + + --text-primary: #fafafa; + --text-secondary: #a1a1aa; + --text-tertiary: #71717a; + --text-link: #818cf8; + --text-link-hover: #a5b4fc; + + --accent-blue: #6366f1; + --accent-blue-bg: rgba(99, 102, 241, 0.1); + --accent-green: #4ade80; + --accent-green-bg: rgba(74, 222, 128, 0.08); + --accent-red: #f87171; + --accent-red-bg: rgba(248, 113, 113, 0.08); + --accent-yellow: #fbbf24; + --accent-yellow-bg: rgba(251, 191, 36, 0.08); + --accent-purple: #c084fc; + --accent-purple-bg: rgba(192, 132, 252, 0.08); + --accent-orange: #fb923c; + --accent-orange-bg: rgba(251, 146, 60, 0.08); + + --font-sans: 'Inter', -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, sans-serif; + --font-mono: 'JetBrains Mono', 'Fira Code', 'Cascadia Code', monospace; + + --sidebar-width: 260px; + --header-height: 56px; + --content-max-width: 820px; + --transition-fast: 150ms ease; + --transition-normal: 250ms ease; + + --radius-sm: 6px; + --radius-md: 8px; + --radius-lg: 12px; +} + +html { + scroll-behavior: smooth; + -webkit-text-size-adjust: 100%; +} + +body { + font-family: var(--font-sans); + font-size: 15px; + line-height: 1.7; + color: var(--text-primary); + background: var(--bg-primary); + -webkit-font-smoothing: antialiased; + -moz-osx-font-smoothing: grayscale; + overflow-x: hidden; +} + +a { + color: var(--text-link); + text-decoration: none; + transition: color var(--transition-fast); +} + +a:hover { + color: var(--text-link-hover); +} + +/* ===== Top Navigation ===== */ +.top-nav { + position: fixed; + top: 0; + left: 0; + right: 0; + height: var(--header-height); + background: rgba(15, 15, 16, 0.85); + backdrop-filter: blur(12px); + -webkit-backdrop-filter: blur(12px); + border-bottom: 1px solid var(--border-subtle); + z-index: 100; +} + +.top-nav-inner { + max-width: 100%; + height: 100%; + display: flex; + align-items: center; + justify-content: space-between; + padding: 0 20px; +} + +.top-nav-left { + display: flex; + align-items: center; + gap: 12px; +} + +.top-nav-right { + display: flex; + align-items: center; + gap: 16px; +} + +.sidebar-toggle { + display: none; + background: none; + border: none; + color: var(--text-secondary); + cursor: pointer; + padding: 4px; + border-radius: var(--radius-sm); + transition: color var(--transition-fast); +} + +.sidebar-toggle:hover { + color: var(--text-primary); +} + +.logo-link { + display: flex; + align-items: center; + gap: 10px; + color: var(--text-primary); + font-weight: 600; + font-size: 15px; + text-decoration: none; +} + +.logo-svg { + width: 28px; + height: 28px; + border-radius: 6px; +} + +.logo-divider { + width: 1px; + height: 16px; + background: var(--border-default); +} + +.logo-docs { + color: var(--text-secondary); + font-weight: 500; +} + +.search-bar { + display: flex; + align-items: center; + gap: 8px; + padding: 6px 12px; + border-radius: var(--radius-md); + border: 1px solid var(--border-subtle); + background: var(--bg-secondary); + cursor: pointer; + transition: all var(--transition-fast); + min-width: 240px; +} + +.search-bar:hover { + border-color: var(--border-default); + background: var(--bg-tertiary); +} + +.search-icon { + color: var(--text-tertiary); + flex-shrink: 0; +} + +.search-bar input { + background: none; + border: none; + color: var(--text-secondary); + font-family: var(--font-sans); + font-size: 13px; + outline: none; + flex: 1; + cursor: pointer; +} + +.search-bar input::placeholder { + color: var(--text-tertiary); +} + +.search-shortcut { + font-size: 11px; + color: var(--text-tertiary); + background: var(--bg-elevated); + padding: 2px 6px; + border-radius: 4px; + border: 1px solid var(--border-subtle); + font-family: var(--font-sans); +} + +.nav-link { + font-size: 13px; + color: var(--text-secondary); + font-weight: 500; + transition: color var(--transition-fast); +} + +.nav-link:hover { + color: var(--text-primary); +} + +/* ===== Layout ===== */ +.layout { + display: flex; + min-height: 100vh; + padding-top: var(--header-height); +} + +/* ===== Sidebar ===== */ +.sidebar { + position: fixed; + top: var(--header-height); + left: 0; + width: var(--sidebar-width); + height: calc(100vh - var(--header-height)); + overflow-y: auto; + background: var(--bg-primary); + border-right: 1px solid var(--border-subtle); + padding: 16px 0; + z-index: 50; +} + +.sidebar::-webkit-scrollbar { + width: 4px; +} + +.sidebar::-webkit-scrollbar-track { + background: transparent; +} + +.sidebar::-webkit-scrollbar-thumb { + background: var(--border-subtle); + border-radius: 4px; +} + +.sidebar-nav { + display: flex; + flex-direction: column; + gap: 4px; +} + +.nav-section { + padding: 0 12px; + margin-bottom: 8px; +} + +.nav-section-title { + font-size: 11px; + font-weight: 600; + text-transform: uppercase; + letter-spacing: 0.05em; + color: var(--text-tertiary); + padding: 8px 12px 6px; + margin-top: 8px; +} + +.nav-section:first-child .nav-section-title { + margin-top: 0; +} + +.nav-item { + display: block; + padding: 6px 12px; + font-size: 13.5px; + color: var(--text-secondary); + border-radius: var(--radius-sm); + transition: all var(--transition-fast); + text-decoration: none; + font-weight: 450; +} + +.nav-item:hover { + color: var(--text-primary); + background: var(--bg-hover); +} + +.nav-item.active { + color: var(--text-primary); + background: var(--accent-blue-bg); + font-weight: 500; +} + +.sidebar-overlay { + display: none; +} + +/* ===== Content ===== */ +.content { + margin-left: var(--sidebar-width); + flex: 1; + min-width: 0; + padding: 40px 48px 80px; +} + +.page { + max-width: var(--content-max-width); + margin: 0 auto; +} + +/* Page Header */ +.page-header { + position: relative; + margin-bottom: 40px; + padding-bottom: 24px; + border-bottom: 1px solid var(--border-subtle); +} + +.copy-page-btn { + position: absolute; + top: 0; + right: 0; + display: flex; + align-items: center; + gap: 6px; + padding: 6px 12px; + background: var(--bg-secondary); + border: 1px solid var(--border-subtle); + border-radius: var(--radius-sm); + color: var(--text-tertiary); + font-family: var(--font-sans); + font-size: 12px; + font-weight: 500; + cursor: pointer; + transition: all var(--transition-fast); + white-space: nowrap; +} + +.copy-page-btn:hover { + color: var(--text-primary); + border-color: var(--border-default); + background: var(--bg-tertiary); +} + +.copy-page-btn .copied { + color: var(--accent-green); +} + +.breadcrumb { + font-size: 12px; + font-weight: 500; + text-transform: uppercase; + letter-spacing: 0.05em; + color: var(--accent-blue); + margin-bottom: 8px; +} + +.page-header h1 { + font-size: 36px; + font-weight: 700; + line-height: 1.2; + letter-spacing: -0.02em; + color: var(--text-primary); + margin-bottom: 12px; +} + +.page-subtitle { + font-size: 17px; + color: var(--text-secondary); + line-height: 1.6; +} + +/* Typography */ +h2 { + font-size: 24px; + font-weight: 650; + letter-spacing: -0.01em; + color: var(--text-primary); + margin-top: 48px; + margin-bottom: 16px; + padding-top: 16px; + border-top: 1px solid var(--border-subtle); +} + +h2:first-of-type { + border-top: none; + padding-top: 0; +} + +h3 { + font-size: 18px; + font-weight: 600; + color: var(--text-primary); + margin-top: 32px; + margin-bottom: 12px; +} + +h4 { + font-size: 15px; + font-weight: 600; + color: var(--text-primary); + margin-top: 24px; + margin-bottom: 8px; +} + +p { + margin-bottom: 16px; + color: var(--text-secondary); +} + +ul, ol { + margin-bottom: 16px; + padding-left: 24px; +} + +li { + margin-bottom: 6px; + color: var(--text-secondary); +} + +li strong { + color: var(--text-primary); +} + +code { + font-family: var(--font-mono); + font-size: 13px; + background: var(--bg-elevated); + padding: 2px 6px; + border-radius: 4px; + color: var(--accent-purple); + border: 1px solid var(--border-subtle); +} + +.direction { + font-size: 12px; + color: var(--text-tertiary); + font-weight: 400; + margin-left: 4px; +} + +/* ===== Code Blocks ===== */ +.code-block { + margin-bottom: 20px; + border: 1px solid var(--border-subtle); + border-radius: var(--radius-md); + overflow: hidden; + background: var(--bg-secondary); +} + +.code-header { + display: flex; + align-items: center; + justify-content: space-between; + padding: 8px 16px; + background: var(--bg-tertiary); + border-bottom: 1px solid var(--border-subtle); + font-size: 12px; + color: var(--text-tertiary); + font-weight: 500; +} + +.copy-actions { + display: flex; + gap: 4px; +} + +.copy-btn { + background: none; + border: 1px solid var(--border-subtle); + color: var(--text-tertiary); + padding: 2px 10px; + border-radius: 4px; + font-size: 11px; + cursor: pointer; + font-family: var(--font-sans); + transition: all var(--transition-fast); + white-space: nowrap; +} + +.copy-btn:hover { + color: var(--text-primary); + border-color: var(--border-default); + background: var(--bg-hover); +} + +.copy-btn.copied { + color: var(--accent-green); + border-color: rgba(74, 222, 128, 0.3); +} + +.code-block pre { + padding: 16px; + overflow-x: auto; + margin: 0; +} + +.code-block code { + font-family: var(--font-mono); + font-size: 13px; + line-height: 1.6; + color: var(--text-primary); + background: none; + padding: 0; + border: none; + border-radius: 0; +} + +/* ===== Tables ===== */ +.doc-table { + width: 100%; + border-collapse: collapse; + margin-bottom: 24px; + font-size: 14px; +} + +.doc-table thead { + background: var(--bg-tertiary); +} + +.doc-table th { + text-align: left; + padding: 10px 16px; + font-weight: 600; + color: var(--text-primary); + border-bottom: 1px solid var(--border-default); + font-size: 13px; +} + +.doc-table td { + padding: 10px 16px; + border-bottom: 1px solid var(--border-subtle); + color: var(--text-secondary); + vertical-align: top; +} + +.doc-table tr:last-child td { + border-bottom: none; +} + +.doc-table tr:hover td { + background: var(--bg-hover); +} + +/* ===== Badges ===== */ +.badge { + display: inline-block; + padding: 2px 8px; + border-radius: 10px; + font-size: 11px; + font-weight: 600; + letter-spacing: 0.02em; + white-space: nowrap; +} + +.badge-green { + background: var(--accent-green-bg); + color: var(--accent-green); + border: 1px solid rgba(74, 222, 128, 0.2); +} + +.badge-red { + background: var(--accent-red-bg); + color: var(--accent-red); + border: 1px solid rgba(248, 113, 113, 0.2); +} + +.badge-blue { + background: var(--accent-blue-bg); + color: #818cf8; + border: 1px solid rgba(99, 102, 241, 0.2); +} + +.badge-purple { + background: var(--accent-purple-bg); + color: var(--accent-purple); + border: 1px solid rgba(192, 132, 252, 0.2); +} + +.badge-orange { + background: var(--accent-orange-bg); + color: var(--accent-orange); + border: 1px solid rgba(251, 146, 60, 0.2); +} + +.badge-yellow { + background: var(--accent-yellow-bg); + color: var(--accent-yellow); + border: 1px solid rgba(251, 191, 36, 0.2); +} + +/* ===== Callouts ===== */ +.callout { + display: flex; + gap: 12px; + padding: 16px 20px; + border-radius: var(--radius-md); + margin-bottom: 24px; + border: 1px solid; +} + +.callout-icon { + flex-shrink: 0; + margin-top: 1px; +} + +.callout-content { + font-size: 14px; + line-height: 1.6; + color: var(--text-secondary); +} + +.callout-content strong { + color: var(--text-primary); +} + +.callout-content a { + color: var(--text-link); +} + +.callout-info { + background: var(--accent-blue-bg); + border-color: rgba(99, 102, 241, 0.2); +} + +.callout-info .callout-icon { + color: var(--accent-blue); +} + +.callout-warning { + background: var(--accent-yellow-bg); + border-color: rgba(251, 191, 36, 0.2); +} + +.callout-warning .callout-icon { + color: var(--accent-yellow); +} + +.callout-tip { + background: var(--accent-green-bg); + border-color: rgba(74, 222, 128, 0.2); +} + +.callout-tip .callout-icon { + color: var(--accent-green); +} + +/* ===== Feature Grid ===== */ +.feature-grid { + display: grid; + grid-template-columns: repeat(2, 1fr); + gap: 16px; + margin-bottom: 24px; +} + +.feature-card { + padding: 24px; + background: var(--bg-secondary); + border: 1px solid var(--border-subtle); + border-radius: var(--radius-lg); + transition: all var(--transition-normal); +} + +.feature-card:hover { + border-color: var(--border-default); + background: var(--bg-tertiary); + transform: translateY(-1px); +} + +.feature-icon { + font-size: 28px; + margin-bottom: 12px; +} + +.feature-card h3 { + font-size: 16px; + font-weight: 600; + margin-top: 0; + margin-bottom: 8px; + color: var(--text-primary); +} + +.feature-card p { + font-size: 14px; + color: var(--text-secondary); + margin-bottom: 0; + line-height: 1.5; +} + +/* ===== Diagrams ===== */ +.diagram-container { + margin-bottom: 24px; + border: 1px solid var(--border-subtle); + border-radius: var(--radius-md); + overflow-x: auto; + background: var(--bg-secondary); +} + +.diagram { + font-family: var(--font-mono); + font-size: 12.5px; + line-height: 1.5; + color: var(--text-secondary); + padding: 20px 24px; + margin: 0; + white-space: pre; +} + +/* ===== Two Column Layout ===== */ +.two-col { + display: grid; + grid-template-columns: 1fr 1fr; + gap: 24px; + margin-bottom: 24px; +} + +/* ===== Phase Cards ===== */ +.phase-card { + padding: 24px; + border: 1px solid var(--border-subtle); + border-radius: var(--radius-lg); + margin-bottom: 24px; + background: var(--bg-secondary); +} + +.phase-header { + display: flex; + align-items: center; + gap: 12px; + margin-bottom: 16px; + font-weight: 500; + color: var(--text-primary); +} + +.phase-card ul { + margin-bottom: 0; +} + +/* ===== Accordion ===== */ +.accordion { + margin-bottom: 24px; +} + +details { + border: 1px solid var(--border-subtle); + border-radius: var(--radius-md); + margin-bottom: 8px; + overflow: hidden; +} + +summary { + padding: 12px 16px; + cursor: pointer; + font-weight: 500; + color: var(--text-primary); + background: var(--bg-secondary); + transition: background var(--transition-fast); + list-style: none; +} + +summary::-webkit-details-marker { + display: none; +} + +summary::before { + content: '>'; + display: inline-block; + margin-right: 8px; + font-family: var(--font-mono); + font-size: 12px; + color: var(--text-tertiary); + transition: transform var(--transition-fast); +} + +details[open] summary::before { + transform: rotate(90deg); +} + +summary:hover { + background: var(--bg-tertiary); +} + +.accordion-content { + padding: 16px; + border-top: 1px solid var(--border-subtle); + background: var(--bg-primary); +} + +/* ===== Checklist ===== */ +.checklist { + list-style: none; + padding-left: 0; +} + +.checklist li { + padding-left: 24px; + position: relative; +} + +.checklist li::before { + content: ''; + position: absolute; + left: 0; + top: 7px; + width: 14px; + height: 14px; + border: 1.5px solid var(--border-default); + border-radius: 3px; +} + +/* ===== Color Swatches ===== */ +.color-swatch { + display: inline-block; + width: 14px; + height: 14px; + border-radius: 3px; + vertical-align: middle; + margin-right: 4px; + border: 1px solid var(--border-default); +} + +/* ===== Footer ===== */ +.page-footer { + max-width: var(--content-max-width); + margin: 60px auto 0; + border-top: 1px solid var(--border-subtle); + padding-top: 24px; +} + +.footer-nav { + display: flex; + justify-content: space-between; + gap: 24px; + margin-bottom: 32px; +} + +.footer-prev, .footer-next { + display: flex; + flex-direction: column; + padding: 16px 20px; + border: 1px solid var(--border-subtle); + border-radius: var(--radius-md); + text-decoration: none; + transition: all var(--transition-fast); + min-width: 200px; +} + +.footer-next { + text-align: right; + margin-left: auto; +} + +.footer-prev:hover, .footer-next:hover { + border-color: var(--border-default); + background: var(--bg-secondary); +} + +.footer-label { + font-size: 11px; + font-weight: 600; + text-transform: uppercase; + letter-spacing: 0.05em; + color: var(--text-tertiary); + margin-bottom: 4px; +} + +.footer-title { + font-size: 15px; + font-weight: 500; + color: var(--text-link); +} + +.footer-meta { + text-align: center; + padding: 16px 0; +} + +.footer-meta p { + font-size: 12px; + color: var(--text-tertiary); +} + +/* ===== Search Modal ===== */ +.search-modal { + position: fixed; + inset: 0; + z-index: 200; + display: flex; + align-items: flex-start; + justify-content: center; + padding-top: 120px; +} + +.search-modal-overlay { + position: absolute; + inset: 0; + background: rgba(0, 0, 0, 0.6); + backdrop-filter: blur(4px); +} + +.search-modal-content { + position: relative; + width: 560px; + max-height: 400px; + background: var(--bg-secondary); + border: 1px solid var(--border-default); + border-radius: var(--radius-lg); + box-shadow: 0 24px 64px rgba(0, 0, 0, 0.5); + overflow: hidden; +} + +.search-modal-input-wrap { + display: flex; + align-items: center; + gap: 12px; + padding: 16px 20px; + border-bottom: 1px solid var(--border-subtle); + color: var(--text-tertiary); +} + +.search-modal-input-wrap input { + flex: 1; + background: none; + border: none; + color: var(--text-primary); + font-family: var(--font-sans); + font-size: 16px; + outline: none; +} + +.search-modal-input-wrap input::placeholder { + color: var(--text-tertiary); +} + +.search-modal-input-wrap kbd { + font-size: 11px; + color: var(--text-tertiary); + background: var(--bg-elevated); + padding: 2px 6px; + border-radius: 4px; + border: 1px solid var(--border-subtle); + font-family: var(--font-sans); +} + +.search-results { + max-height: 320px; + overflow-y: auto; + padding: 8px; +} + +.search-result-item { + display: block; + padding: 10px 12px; + border-radius: var(--radius-sm); + cursor: pointer; + text-decoration: none; + transition: background var(--transition-fast); +} + +.search-result-item:hover, +.search-result-item.active { + background: var(--bg-hover); +} + +.search-result-section { + font-size: 11px; + color: var(--text-tertiary); + font-weight: 500; + text-transform: uppercase; + letter-spacing: 0.03em; +} + +.search-result-title { + font-size: 14px; + color: var(--text-primary); + font-weight: 500; +} + +.search-no-results { + padding: 24px; + text-align: center; + color: var(--text-tertiary); + font-size: 14px; +} + +/* ===== Responsive ===== */ +@media (max-width: 1024px) { + .content { + padding: 32px 32px 60px; + } +} + +@media (max-width: 768px) { + .sidebar-toggle { + display: block; + } + + .sidebar { + transform: translateX(-100%); + transition: transform var(--transition-normal); + z-index: 90; + background: var(--bg-primary); + } + + .sidebar.open { + transform: translateX(0); + } + + .sidebar-overlay { + position: fixed; + inset: 0; + background: rgba(0, 0, 0, 0.5); + z-index: 80; + opacity: 0; + pointer-events: none; + transition: opacity var(--transition-normal); + } + + .sidebar-overlay.visible { + opacity: 1; + pointer-events: auto; + } + + .content { + margin-left: 0; + padding: 24px 20px 60px; + } + + .page-header h1 { + font-size: 28px; + } + + .feature-grid { + grid-template-columns: 1fr; + } + + .two-col { + grid-template-columns: 1fr; + } + + .search-bar { + min-width: 0; + flex: 1; + max-width: 200px; + } + + .search-shortcut { + display: none; + } + + .search-modal-content { + width: calc(100% - 32px); + margin: 0 16px; + } + + .search-modal { + padding-top: 80px; + } + + .footer-nav { + flex-direction: column; + } + + .footer-prev, .footer-next { + min-width: 0; + } + + .footer-next { + margin-left: 0; + } + + .doc-table { + font-size: 13px; + } + + .doc-table th, .doc-table td { + padding: 8px 10px; + } + + h2 { + font-size: 20px; + } + + h3 { + font-size: 16px; + } +} + +/* ===== Scrollbar ===== */ +::-webkit-scrollbar { + width: 6px; + height: 6px; +} + +::-webkit-scrollbar-track { + background: transparent; +} + +::-webkit-scrollbar-thumb { + background: var(--border-subtle); + border-radius: 4px; +} + +::-webkit-scrollbar-thumb:hover { + background: var(--border-default); +} + +/* ===== Selection ===== */ +::selection { + background: rgba(99, 102, 241, 0.3); + color: var(--text-primary); +} + +/* ===== Smooth page transitions ===== */ +.page { + animation: fadeIn 200ms ease; +} + +@keyframes fadeIn { + from { opacity: 0; transform: translateY(4px); } + to { opacity: 1; transform: translateY(0); } +} + +/* ===== Loading Spinner ===== */ +.page-loading { + display: flex; + justify-content: center; + align-items: center; + min-height: 300px; +} + +.loading-spinner { + width: 28px; + height: 28px; + border: 2.5px solid var(--border-subtle); + border-top-color: var(--accent-blue); + border-radius: 50%; + animation: spin 0.7s linear infinite; +} + +@keyframes spin { + to { transform: rotate(360deg); } +}

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 K3!jZuD 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 z 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