diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000000000000000000000000000000000000..3ed169024be361356d7411de1026affd6ee3aab2 --- /dev/null +++ b/.gitignore @@ -0,0 +1,53 @@ +# 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 +rf_env/ +releases/ +*.so +*.png +*.tflite +*.a +*.zip +*.jar diff --git a/.metadata b/.metadata new file mode 100644 index 0000000000000000000000000000000000000000..89db5de5c40aeb929b683dacf0024311da2e3b10 --- /dev/null +++ b/.metadata @@ -0,0 +1,45 @@ +# 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 + - platform: ios + create_revision: ff37bef603469fb030f2b72995ab929ccfc227f0 + base_revision: ff37bef603469fb030f2b72995ab929ccfc227f0 + - platform: linux + create_revision: ff37bef603469fb030f2b72995ab929ccfc227f0 + base_revision: ff37bef603469fb030f2b72995ab929ccfc227f0 + - platform: macos + create_revision: ff37bef603469fb030f2b72995ab929ccfc227f0 + base_revision: ff37bef603469fb030f2b72995ab929ccfc227f0 + - platform: web + create_revision: ff37bef603469fb030f2b72995ab929ccfc227f0 + base_revision: ff37bef603469fb030f2b72995ab929ccfc227f0 + - platform: windows + 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/README.md b/README.md new file mode 100644 index 0000000000000000000000000000000000000000..69a83d6c5e7594933200765e72aea45acaef7224 --- /dev/null +++ b/README.md @@ -0,0 +1,60 @@ +--- +title: Prem +emoji: 🔥 +colorFrom: red +colorTo: yellow +sdk: static +pinned: false +short_description: In device co-pilot +--- +# Premithius V0.0.3 +**India-First On-Device AI Security | Zero LLM Footprint | ARMadillo Architecture** + +Premithius is an uncompromising, edge-native security layer for Android devices. Designed specifically for the Indian cybersecurity context, it proactively intercepts sophisticated threats like ₹1 collect requests, Aadhaar/PAN data leaks, and zero-day scams before they ever reach the user's eyes—all without sending a single byte of personal data to the cloud. + +--- + +## 🛡️ Kavacha Engine (5-Layer Defense) +Inspired by NVIDIA's ARMadillo architecture, Premithius utilizes a DOCA FLOW-style early-exit pipeline. This ensures maximum efficiency, allowing standard traffic to pass cleanly while trapping anomalies with progressive computational weight. + +1. **Layer 0 (Whitelist):** Immediate pass for trusted, verified senders. +2. **Layer 1 (India Threat Pack):** Hardened heuristic rules targeting specific local threat vectors (see below). +3. **Layer 2 (Vector Similarity):** Sub-millisecond KNN semantic search against offline scam embeddings using `sqlite-vec` (ARM NEON accelerated). +4. **Layer 3 (Random Forest):** A lightweight trained ensemble classifier exported to pure Dart via `m2cgen`. Trained on the HuggingFace `india-spam-sms` dataset with 13 custom numerical and categorical features. Scales dynamically during high-risk festival periods. +5. **Layer 4 (MobileBERT):** Our final deep-learning fallback layer. Integrates the `mrm8488/bert-tiny-finetuned-sms-spam-detection` model running locally via `tflite_flutter` and a custom-built native Dart WordPiece tokenizer. + +--- + +## 🇮🇳 India Threat Pack +Premithius is built for the ground reality of Indian digital fraud: + +* **UPI Firewall:** Natively catches the classic "₹1 collect request" marketplace fraud, scanning for suspicious VPA usage and urgency indicators. +* **OTP Context Verifier:** Intercepts incoming OTP messages and cross-references them against the active foreground application to prevent OTP-forwarding phishing. +* **Aadhaar/PAN Data Shield:** A final line of defense baked directly into the custom Premithius Keyboard, warning users *before* they inadvertently send sensitive documents to untrusted contacts. +* **Festival Calendar:** Scam volume spikes ~340% during major holidays. The pipeline dynamically adjusts its sensitivity multiplier during these critical windows. + +--- + +## 🚀 Edge-Native & Privacy First +* **Zero LLM Overhead:** V0.0.3 maintains a tiny footprint by running Random Forest directly in Dart arithmetic and utilizing a highly optimized, quantized BERT module instead of a 900MB Qwen2 model. +* **Data Shield Insights**: A custom Android native Kotlin telemetry layer continuously and securely queries `AppOpsManager` and `UsageStatsManager` in the background. It surfaces hardware access events (Mic/Camera) and compiles local privacy stories translating background behavior for users. +* **Home Screen Widget**: A completely native Kotlin AppWidget provides users with 4x2 interactive real-time monitoring of their device's security status, avoiding Flutter engine wakelocks entirely. + +--- + +## 🛠️ Build Requirements + +* Flutter SDK (^3.11.1) +* Android Studio / Android SDK +* *Note:* The final release build requires the `sqlite-vec-android:0.1.7` dependency. Ensure your Android `build.gradle` is configured with the correct Maven artifact repositories if retrieving `io.github.asg017` fails during compilation. + +```bash +# Debug Build +flutter build apk --debug + +# Release Build +flutter build apk --release +``` + +--- +*Built for the next billion users. Because security shouldn't require surrendering your privacy.* diff --git a/analysis_options.yaml b/analysis_options.yaml new file mode 100644 index 0000000000000000000000000000000000000000..0d2902135caece481a035652d88970c80e29cc7e --- /dev/null +++ b/analysis_options.yaml @@ -0,0 +1,28 @@ +# This file configures the analyzer, which statically analyzes Dart code to +# check for errors, warnings, and lints. +# +# The issues identified by the analyzer are surfaced in the UI of Dart-enabled +# IDEs (https://dart.dev/tools#ides-and-editors). The analyzer can also be +# invoked from the command line by running `flutter analyze`. + +# The following line activates a set of recommended lints for Flutter apps, +# packages, and plugins designed to encourage good coding practices. +include: package:flutter_lints/flutter.yaml + +linter: + # The lint rules applied to this project can be customized in the + # section below to disable rules from the `package:flutter_lints/flutter.yaml` + # included above or to enable additional rules. A list of all available lints + # and their documentation is published at https://dart.dev/lints. + # + # Instead of disabling a lint rule for the entire project in the + # section below, it can also be suppressed for a single line of code + # or a specific dart file by using the `// ignore: name_of_lint` and + # `// ignore_for_file: name_of_lint` syntax on the line or in the file + # producing the lint. + rules: + # avoid_print: false # Uncomment to disable the `avoid_print` rule + # prefer_single_quotes: true # Uncomment to enable the `prefer_single_quotes` rule + +# Additional information about this file can be found at +# https://dart.dev/guides/language/analysis-options diff --git a/analyze_current.txt b/analyze_current.txt new file mode 100644 index 0000000000000000000000000000000000000000..d0cf4efd3001e5e9ced43a51d4ade5ed607617d3 --- /dev/null +++ b/analyze_current.txt @@ -0,0 +1,39 @@ +Analyzing premithus... + + info • Don't invoke 'print' in production code • lib/kavacha/kavacha_pipeline.dart:34:5 • avoid_print +warning • Unused import: 'package:sqflite/sqflite.dart' • lib/kavacha/layers/layer0_whitelist.dart:1:8 • unused_import + info • Don't invoke 'print' in production code • lib/kavacha/layers/layer4_mobile_bert.dart:15:7 • avoid_print + info • Parameter 'key' could be a super parameter • lib/keyboard/keyboard_layout.dart:12:9 • use_super_parameters + info • Invalid use of a private type in a public API • lib/keyboard/keyboard_layout.dart:15:3 • library_private_types_in_public_api +warning • The value of the field '_hinglish' isn't used • lib/keyboard/keyboard_layout.dart:24:9 • unused_field + info • Don't use 'BuildContext's across async gaps • lib/keyboard/keyboard_layout.dart:84:35 • use_build_context_synchronously + info • Parameter 'key' could be a super parameter • lib/keyboard/shortcut_bar.dart:7:9 • use_super_parameters + info • 'withOpacity' is deprecated and shouldn't be used. Use .withValues() to avoid precision loss • lib/keyboard/shortcut_bar.dart:39:24 • deprecated_member_use + info • 'withOpacity' is deprecated and shouldn't be used. Use .withValues() to avoid precision loss • lib/keyboard/shortcut_bar.dart:41:43 • deprecated_member_use + info • Parameter 'key' could be a super parameter • lib/main.dart:57:9 • use_super_parameters + info • Parameter 'key' could be a super parameter • lib/onboarding/model_download.dart:6:9 • use_super_parameters + info • Invalid use of a private type in a public API • lib/onboarding/model_download.dart:9:3 • library_private_types_in_public_api + info • Parameter 'key' could be a super parameter • lib/onboarding/permission_flow.dart:6:9 • use_super_parameters + info • Invalid use of a private type in a public API • lib/onboarding/permission_flow.dart:9:3 • library_private_types_in_public_api + info • Parameter 'key' could be a super parameter • lib/screens/data_shield_screen.dart:4:9 • use_super_parameters + info • 'withOpacity' is deprecated and shouldn't be used. Use .withValues() to avoid precision loss • lib/screens/data_shield_screen.dart:73:33 • deprecated_member_use + info • 'withOpacity' is deprecated and shouldn't be used. Use .withValues() to avoid precision loss • lib/screens/data_shield_screen.dart:83:36 • deprecated_member_use + info • Don't invoke 'print' in production code • lib/services/grammar_service.dart:14:5 • avoid_print + info • The private field _isInit could be 'final' • lib/services/llm_service.dart:8:8 • prefer_final_fields +warning • The value of the field '_isInit' isn't used • lib/services/llm_service.dart:8:8 • unused_field +warning • Unused import: 'package:flutter/services.dart' • lib/services/scam_service.dart:1:8 • unused_import +warning • Unused import: 'package:tflite_flutter/tflite_flutter.dart' • lib/services/scam_service.dart:2:8 • unused_import + info • Don't invoke 'print' in production code • lib/services/scam_service.dart:38:7 • avoid_print + info • Don't invoke 'print' in production code • lib/services/scam_service.dart:40:7 • avoid_print + info • Don't invoke 'print' in production code • lib/services/scam_service.dart:62:9 • avoid_print + info • Don't invoke 'print' in production code • lib/services/scam_service.dart:86:7 • avoid_print + info • The imported package 'path' isn't a dependency of the importing package • lib/services/storage_service.dart:2:8 • depend_on_referenced_packages + info • The imported package 'path' isn't a dependency of the importing package • lib/services/vector_service.dart:4:8 • depend_on_referenced_packages +warning • Unused import: 'package:path/path.dart' • lib/services/vector_service.dart:4:8 • unused_import + info • Don't invoke 'print' in production code • lib/services/vector_service.dart:57:7 • avoid_print + info • Don't invoke 'print' in production code • lib/services/vector_service.dart:59:7 • avoid_print + info • Don't invoke 'print' in production code • lib/services/vector_service.dart:66:5 • avoid_print + info • Don't invoke 'print' in production code • lib/services/vector_service.dart:78:5 • avoid_print + info • Don't invoke 'print' in production code • lib/services/vector_service.dart:113:7 • avoid_print + +35 issues found. (ran in 4.7s) diff --git a/analyze_final.txt b/analyze_final.txt new file mode 100644 index 0000000000000000000000000000000000000000..336f89b73eb03ad67d17a50cb91162fcdad76bac --- /dev/null +++ b/analyze_final.txt @@ -0,0 +1,29 @@ +Analyzing premithus... + + info • Don't invoke 'print' in production code • lib/kavacha/kavacha_pipeline.dart:34:5 • avoid_print +warning • Unused import: 'package:sqflite/sqflite.dart' • lib/kavacha/layers/layer0_whitelist.dart:1:8 • unused_import + info • Don't invoke 'print' in production code • lib/kavacha/layers/layer4_mobile_bert.dart:15:7 • avoid_print + info • Parameter 'key' could be a super parameter • lib/keyboard/keyboard_layout.dart:13:9 • use_super_parameters + info • Invalid use of a private type in a public API • lib/keyboard/keyboard_layout.dart:16:3 • library_private_types_in_public_api +warning • The value of the field '_hinglish' isn't used • lib/keyboard/keyboard_layout.dart:25:9 • unused_field + info • Don't use 'BuildContext's across async gaps • lib/keyboard/keyboard_layout.dart:85:35 • use_build_context_synchronously + info • Parameter 'key' could be a super parameter • lib/keyboard/shortcut_bar.dart:9:9 • use_super_parameters + info • Parameter 'key' could be a super parameter • lib/main.dart:57:9 • use_super_parameters + info • Parameter 'key' could be a super parameter • lib/onboarding/model_download.dart:6:9 • use_super_parameters + info • Invalid use of a private type in a public API • lib/onboarding/model_download.dart:9:3 • library_private_types_in_public_api + info • Invalid use of a private type in a public API • lib/onboarding/permission_flow.dart:11:3 • library_private_types_in_public_api + info • Don't invoke 'print' in production code • lib/services/grammar_service.dart:14:5 • avoid_print + info • The private field _isInit could be 'final' • lib/services/llm_service.dart:8:8 • prefer_final_fields +warning • The value of the field '_isInit' isn't used • lib/services/llm_service.dart:8:8 • unused_field +warning • Duplicate import • lib/services/scam_service.dart:5:8 • duplicate_import +warning • Duplicate import • lib/services/scam_service.dart:6:8 • duplicate_import + error • A try block must be followed by an 'on', 'catch', or 'finally' clause • lib/services/scam_service.dart:35:5 • missing_catch_or_finally + error • Expected to find '}' • lib/services/scam_service.dart:38:3 • expected_token + info • Don't invoke 'print' in production code • lib/services/scam_service.dart:82:7 • avoid_print + info • Don't invoke 'print' in production code • lib/services/vector_service.dart:56:7 • avoid_print + info • Don't invoke 'print' in production code • lib/services/vector_service.dart:58:7 • avoid_print + info • Don't invoke 'print' in production code • lib/services/vector_service.dart:65:5 • avoid_print + info • Don't invoke 'print' in production code • lib/services/vector_service.dart:77:5 • avoid_print + info • Don't invoke 'print' in production code • lib/services/vector_service.dart:112:7 • avoid_print + +25 issues found. (ran in 3.5s) diff --git a/analyze_out.txt b/analyze_out.txt new file mode 100644 index 0000000000000000000000000000000000000000..6ca2df875e85b2984e024ef382b2844581041165 --- /dev/null +++ b/analyze_out.txt @@ -0,0 +1,63 @@ +Analyzing premithus... + + error • The element type 'Layer3RandomForest' can't be assigned to the list type 'KavachaLayer' • lib/kavacha/kavacha_pipeline.dart:29:7 • list_element_type_not_assignable + info • Don't invoke 'print' in production code • lib/kavacha/kavacha_pipeline.dart:34:5 • avoid_print +warning • Unused import: 'package:sqflite/sqflite.dart' • lib/kavacha/layers/layer0_whitelist.dart:1:8 • unused_import + error • Classes and mixins can only implement other classes and mixins • lib/kavacha/layers/layer3_random_forest.dart:5:37 • implements_non_class + error • The name 'LayerResult' isn't a type, so it can't be used as a type argument • lib/kavacha/layers/layer3_random_forest.dart:9:10 • non_type_as_type_argument +warning • The method doesn't override an inherited method • lib/kavacha/layers/layer3_random_forest.dart:9:23 • override_on_non_overriding_member + error • Undefined class 'SmsContext' • lib/kavacha/layers/layer3_random_forest.dart:9:31 • undefined_class + error • Undefined name 'LayerResult' • lib/kavacha/layers/layer3_random_forest.dart:14:14 • undefined_identifier + error • Undefined name 'LayerResult' • lib/kavacha/layers/layer3_random_forest.dart:17:14 • undefined_identifier + error • Undefined name 'LayerResult' • lib/kavacha/layers/layer3_random_forest.dart:21:12 • undefined_identifier + error • Undefined class 'SmsContext' • lib/kavacha/layers/layer3_random_forest.dart:24:37 • undefined_class + info • Don't invoke 'print' in production code • lib/kavacha/layers/layer4_mobile_bert.dart:15:7 • avoid_print + info • Parameter 'key' could be a super parameter • lib/keyboard/keyboard_layout.dart:12:9 • use_super_parameters + info • Invalid use of a private type in a public API • lib/keyboard/keyboard_layout.dart:15:3 • library_private_types_in_public_api +warning • The value of the field '_hinglish' isn't used • lib/keyboard/keyboard_layout.dart:23:9 • unused_field + error • Undefined name '_grammarService' • lib/keyboard/keyboard_layout.dart:28:5 • undefined_identifier + error • Undefined name '_grammarService' • lib/keyboard/keyboard_layout.dart:39:23 • undefined_identifier + info • Don't use 'BuildContext's across async gaps • lib/keyboard/keyboard_layout.dart:83:35 • use_build_context_synchronously + info • Parameter 'key' could be a super parameter • lib/keyboard/shortcut_bar.dart:7:9 • use_super_parameters + info • 'withOpacity' is deprecated and shouldn't be used. Use .withValues() to avoid precision loss • lib/keyboard/shortcut_bar.dart:39:24 • deprecated_member_use + info • 'withOpacity' is deprecated and shouldn't be used. Use .withValues() to avoid precision loss • lib/keyboard/shortcut_bar.dart:41:43 • deprecated_member_use + info • Parameter 'key' could be a super parameter • lib/main.dart:57:9 • use_super_parameters + info • Parameter 'key' could be a super parameter • lib/onboarding/model_download.dart:6:9 • use_super_parameters + info • Invalid use of a private type in a public API • lib/onboarding/model_download.dart:9:3 • library_private_types_in_public_api + info • Parameter 'key' could be a super parameter • lib/onboarding/permission_flow.dart:6:9 • use_super_parameters + info • Invalid use of a private type in a public API • lib/onboarding/permission_flow.dart:9:3 • library_private_types_in_public_api + info • Parameter 'key' could be a super parameter • lib/screens/data_shield_screen.dart:4:9 • use_super_parameters + info • 'withOpacity' is deprecated and shouldn't be used. Use .withValues() to avoid precision loss • lib/screens/data_shield_screen.dart:73:33 • deprecated_member_use + info • 'withOpacity' is deprecated and shouldn't be used. Use .withValues() to avoid precision loss • lib/screens/data_shield_screen.dart:83:36 • deprecated_member_use + info • Don't invoke 'print' in production code • lib/services/grammar_service.dart:14:5 • avoid_print + info • The imported package 'llama_sdk' isn't a dependency of the importing package • lib/services/llm_service.dart:2:8 • depend_on_referenced_packages + error • Target of URI doesn't exist: 'package:llama_sdk/llama_sdk.dart' • lib/services/llm_service.dart:2:8 • uri_does_not_exist + info • The private field _isDownloading could be 'final' • lib/services/llm_service.dart:12:8 • prefer_final_fields +warning • The value of the field '_isDownloading' isn't used • lib/services/llm_service.dart:12:8 • unused_field + error • Undefined class 'Llama' • lib/services/llm_service.dart:14:3 • undefined_class + error • The method 'Llama' isn't defined for the type 'LlmService' • lib/services/llm_service.dart:26:16 • undefined_method + error • The method 'LlamaController' isn't defined for the type 'LlmService' • lib/services/llm_service.dart:26:22 • undefined_method + info • Don't invoke 'print' in production code • lib/services/llm_service.dart:29:7 • avoid_print + info • Don't invoke 'print' in production code • lib/services/llm_service.dart:31:7 • avoid_print + info • Don't invoke 'print' in production code • lib/services/llm_service.dart:45:5 • avoid_print + error • The method 'UserLlamaMessage' isn't defined for the type 'LlmService' • lib/services/llm_service.dart:67:25 • undefined_method + info • Don't invoke 'print' in production code • lib/services/llm_service.dart:75:7 • avoid_print +warning • Unused import: 'package:flutter/services.dart' • lib/services/scam_service.dart:1:8 • unused_import +warning • Unused import: 'package:tflite_flutter/tflite_flutter.dart' • lib/services/scam_service.dart:2:8 • unused_import + error • Directives must appear before any declarations • lib/services/scam_service.dart:21:3 • directive_after_declaration + error • Directives must appear before any declarations • lib/services/scam_service.dart:22:1 • directive_after_declaration + info • Don't invoke 'print' in production code • lib/services/scam_service.dart:39:7 • avoid_print + info • Don't invoke 'print' in production code • lib/services/scam_service.dart:41:7 • avoid_print + info • Don't invoke 'print' in production code • lib/services/scam_service.dart:63:9 • avoid_print + info • Don't invoke 'print' in production code • lib/services/scam_service.dart:87:7 • avoid_print + info • The imported package 'path' isn't a dependency of the importing package • lib/services/storage_service.dart:2:8 • depend_on_referenced_packages + info • The imported package 'path' isn't a dependency of the importing package • lib/services/vector_service.dart:4:8 • depend_on_referenced_packages +warning • Unused import: 'package:path/path.dart' • lib/services/vector_service.dart:4:8 • unused_import + info • Don't invoke 'print' in production code • lib/services/vector_service.dart:57:7 • avoid_print + info • Don't invoke 'print' in production code • lib/services/vector_service.dart:59:7 • avoid_print + info • Don't invoke 'print' in production code • lib/services/vector_service.dart:66:5 • avoid_print + info • Don't invoke 'print' in production code • lib/services/vector_service.dart:78:5 • avoid_print + info • Don't invoke 'print' in production code • lib/services/vector_service.dart:113:7 • avoid_print +warning • The asset directory 'models/' doesn't exist • pubspec.yaml:74:7 • asset_directory_does_not_exist + error • The name 'MyApp' isn't a class • test/widget_test.dart:16:35 • creation_with_non_type + diff --git a/analyze_verify.txt b/analyze_verify.txt new file mode 100644 index 0000000000000000000000000000000000000000..3f5d95b16db858acc99d9a20e623f9cd8f3f2ad4 --- /dev/null +++ b/analyze_verify.txt @@ -0,0 +1,25 @@ +Analyzing premithus... + + info • Don't invoke 'print' in production code • lib/kavacha/kavacha_pipeline.dart:34:5 • avoid_print +warning • Unused import: 'package:sqflite/sqflite.dart' • lib/kavacha/layers/layer0_whitelist.dart:1:8 • unused_import + info • Don't invoke 'print' in production code • lib/kavacha/layers/layer4_mobile_bert.dart:15:7 • avoid_print + info • Parameter 'key' could be a super parameter • lib/keyboard/keyboard_layout.dart:13:9 • use_super_parameters + info • Invalid use of a private type in a public API • lib/keyboard/keyboard_layout.dart:16:3 • library_private_types_in_public_api +warning • The value of the field '_hinglish' isn't used • lib/keyboard/keyboard_layout.dart:25:9 • unused_field + info • Don't use 'BuildContext's across async gaps • lib/keyboard/keyboard_layout.dart:85:35 • use_build_context_synchronously + info • Parameter 'key' could be a super parameter • lib/keyboard/shortcut_bar.dart:9:9 • use_super_parameters + info • Parameter 'key' could be a super parameter • lib/main.dart:57:9 • use_super_parameters + info • Parameter 'key' could be a super parameter • lib/onboarding/model_download.dart:6:9 • use_super_parameters + info • Invalid use of a private type in a public API • lib/onboarding/model_download.dart:9:3 • library_private_types_in_public_api + info • Invalid use of a private type in a public API • lib/onboarding/permission_flow.dart:11:3 • library_private_types_in_public_api + info • Don't invoke 'print' in production code • lib/services/grammar_service.dart:14:5 • avoid_print + info • The private field _isInit could be 'final' • lib/services/llm_service.dart:8:8 • prefer_final_fields +warning • The value of the field '_isInit' isn't used • lib/services/llm_service.dart:8:8 • unused_field + info • Don't invoke 'print' in production code • lib/services/scam_service.dart:83:7 • avoid_print + info • Don't invoke 'print' in production code • lib/services/vector_service.dart:56:7 • avoid_print + info • Don't invoke 'print' in production code • lib/services/vector_service.dart:58:7 • avoid_print + info • Don't invoke 'print' in production code • lib/services/vector_service.dart:65:5 • avoid_print + info • Don't invoke 'print' in production code • lib/services/vector_service.dart:77:5 • avoid_print + info • Don't invoke 'print' in production code • lib/services/vector_service.dart:112:7 • avoid_print + +21 issues found. (ran in 3.3s) diff --git a/android/.gitignore b/android/.gitignore new file mode 100644 index 0000000000000000000000000000000000000000..be3943c96d8eed92e2a329ce8327616d5e7dc440 --- /dev/null +++ b/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/android/app/build.gradle.kts b/android/app/build.gradle.kts new file mode 100644 index 0000000000000000000000000000000000000000..74728312a0adcd94fca16c7f6976b8b1b662f314 --- /dev/null +++ b/android/app/build.gradle.kts @@ -0,0 +1,53 @@ +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 = "in.inmodel.premithus" + compileSdk = flutter.compileSdkVersion + ndkVersion = flutter.ndkVersion + + compileOptions { + sourceCompatibility = JavaVersion.VERSION_17 + targetCompatibility = JavaVersion.VERSION_17 + } + + kotlinOptions { + jvmTarget = JavaVersion.VERSION_17.toString() + } + + defaultConfig { + // TODO: Specify your own unique Application ID (https://developer.android.com/studio/build/application-id.html). + applicationId = "in.inmodel.premithus" + // 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 + + ndk { + abiFilters += listOf("arm64-v8a") + } + } + + 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 { + // sqlite-vec bundled directly in jniLibs/arm64-v8a/libsqlitevec.so + // No Gradle dependency needed +} diff --git a/android/app/src/debug/AndroidManifest.xml b/android/app/src/debug/AndroidManifest.xml new file mode 100644 index 0000000000000000000000000000000000000000..399f6981d5d35475eb18e6068ae67cdd7c731978 --- /dev/null +++ b/android/app/src/debug/AndroidManifest.xml @@ -0,0 +1,7 @@ + + + + diff --git a/android/app/src/main/AndroidManifest.xml b/android/app/src/main/AndroidManifest.xml new file mode 100644 index 0000000000000000000000000000000000000000..0a1348b86712ba306991f18b277de43a5198dff7 --- /dev/null +++ b/android/app/src/main/AndroidManifest.xml @@ -0,0 +1,108 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/android/app/src/main/kotlin/in/inmodel/premithus/DomainBlocker.kt b/android/app/src/main/kotlin/in/inmodel/premithus/DomainBlocker.kt new file mode 100644 index 0000000000000000000000000000000000000000..c25743a4a48782b9e983256f5a56b5aefd24c777 --- /dev/null +++ b/android/app/src/main/kotlin/in/inmodel/premithus/DomainBlocker.kt @@ -0,0 +1,159 @@ +package `in`.inmodel.premithus + +import android.content.Context +import android.util.Log + +class DomainBlocker(private val context: Context) { + + private val exactBlocklist = HashSet() + private val regexPatterns = mutableListOf>() + private val trustedDomains = HashSet() + + // Known legitimate Indian bank and payment domains + private val trustedBankDomains = setOf( + "hdfcbank.com", "netbanking.hdfcbank.com", + "sbi.co.in", "onlinesbi.sbi.co.in", + "icicibank.com", "imobileapp.icicibank.com", + "axisbank.com", "axisnet.axisbank.com", + "paytm.com", "secure.paytm.com", + "phonepe.com", "api.phonepe.com", + "npci.org.in", "upi.npci.org.in", + "bhimupi.org.in", + "gpay.app", "pay.google.com", + "amazon.in", "pay.amazon.in", + "flipkart.com", + "swiggy.com", "zomato.com", + "irctc.co.in", "indianrail.gov.in", + "incometax.gov.in", "tin.tin.nsdl.com", + "uidai.gov.in", + ) + + init { + loadBlocklists() + trustedDomains.addAll(trustedBankDomains) + } + + private fun loadBlocklists() { + // Load seed blocklist from assets + try { + context.assets.open("blocklist/india_scam_domains.txt") + .bufferedReader() + .forEachLine { line -> + val clean = line.trim().lowercase() + if (clean.isNotEmpty() && !clean.startsWith("#")) { + exactBlocklist.add(clean) + } + } + Log.d("DomainBlocker", "Loaded ${exactBlocklist.size} blocked domains") + } catch (e: Exception) { + Log.e("DomainBlocker", "Failed to load blocklist: \${e.message}") + } + + // Load user-confirmed blocked domains from SQLite via direct path since Flutter owns DB + try { + val dbPath = context.getDatabasePath("premithius.db").absolutePath + val dbFile = java.io.File(dbPath) + if (dbFile.exists()) { + val db = android.database.sqlite.SQLiteDatabase.openDatabase(dbPath, null, android.database.sqlite.SQLiteDatabase.OPEN_READONLY) + val cursor = db.rawQuery("SELECT domain FROM scam_domains", null) + while (cursor.moveToNext()) { + exactBlocklist.add(cursor.getString(0).lowercase()) + } + cursor.close() + db.close() + } + } catch (e: Exception) { + Log.e("DomainBlocker", "Failed to load user domains: \${e.message}") + } + + // Regex patterns for structural scam detection + regexPatterns.addAll(listOf( + // Suspicious TLDs + Regex(""".*\.(xyz|top|click|tk|ml|ga|cf|gq|pw|cc|su)$""") to "Suspicious TLD", + + // Typosquat: known bank name + extra chars + Regex(""".*hdfc.*bank.*(?!hdfcbank\.com)""") to "HDFC Typosquat", + Regex(""".*sbi.*(?!sbi\.co\.in|onlinesbi)""") to "SBI Typosquat", + Regex(""".*icici.*(?!icicibank\.com)""") to "ICICI Typosquat", + Regex(""".*paytm.*(?!paytm\.com)""") to "Paytm Typosquat", + Regex(""".*phonepe.*(?!phonepe\.com)""") to "PhonePe Typosquat", + + // KYC fraud patterns + Regex(""".*kyc.*(update|verify|expire|block).*""") to "KYC Fraud", + Regex(""".*verify.*(kyc|account|aadhar|aadhaar).*""") to "KYC Fraud", + + // UPI fraud patterns + Regex(""".*upi.*(reward|prize|cashback|bonus).*""") to "UPI Fraud", + Regex(""".*collect.*(rs|rupee|inr|money).*""") to "UPI Collect Fraud", + + // Generic phishing patterns + Regex(""".*secure.*login.*\.(xyz|net|org|in|co)$""") to "Phishing", + Regex(""".*account.*(blocked|suspended|expired).*""") to "Account Fraud", + )) + } + + fun check(domain: String): BlockResult { + val d = domain.lowercase().trimEnd('.') + + // Step 1: Trusted domain — always allow instantly + if (trustedDomains.any { d == it || d.endsWith(".$it") }) { + return BlockResult(isBlocked = false, domain = d, category = "") + } + + // Step 2: Exact match in blocklist + if (exactBlocklist.contains(d)) { + return BlockResult(isBlocked = true, domain = d, category = "Known Scam Domain") + } + + // Step 3: Levenshtein distance check against trusted bank domains + // Catches: hdfcbannk.com (typo), hdfcbank-kyc.net (subdomain fraud) + for (trusted in trustedBankDomains) { + val baseTrusted = trusted.substringBefore(".") + val baseQuery = d.substringBefore(".") + if (levenshtein(baseQuery, baseTrusted) in 1..2) { + return BlockResult(isBlocked = true, domain = d, + category = "Typosquat — similar to $trusted") + } + } + + // Step 4: Regex pattern matching + for ((pattern, category) in regexPatterns) { + // Note: need to handle regex exclusion properly. Since patterns above use negative lookahead incorrectly for exact strings, we might want to ensure we don't block valid domains. + // Actually the negative lookahead matches at current position. Because Android Kotlin PCRE works. + if (pattern.containsMatchIn(d)) { + return BlockResult(isBlocked = true, domain = d, category = category) + } + } + + // Step 5: Allow — not in any blocklist + return BlockResult(isBlocked = false, domain = d, category = "") + } + + // Levenshtein distance — pure Kotlin, no library needed + private fun levenshtein(a: String, b: String): Int { + val dp = Array(a.length + 1) { IntArray(b.length + 1) } + for (i in 0..a.length) dp[i][0] = i + for (j in 0..b.length) dp[0][j] = j + for (i in 1..a.length) { + for (j in 1..b.length) { + dp[i][j] = if (a[i-1] == b[j-1]) dp[i-1][j-1] + else 1 + minOf(dp[i-1][j], dp[i][j-1], dp[i-1][j-1]) + } + } + return dp[a.length][b.length] + } + + // Reload user-confirmed domains from SQLite + // Call after user confirms a scam domain + fun reload() { + exactBlocklist.clear() + regexPatterns.clear() + loadBlocklists() + } +} + +data class BlockResult( + val isBlocked: Boolean, + val domain: String, + val category: String +) diff --git a/android/app/src/main/kotlin/in/inmodel/premithus/KavachaVpnService.kt b/android/app/src/main/kotlin/in/inmodel/premithus/KavachaVpnService.kt new file mode 100644 index 0000000000000000000000000000000000000000..9969463d44a95bb047296ef61e4728f961c82165 --- /dev/null +++ b/android/app/src/main/kotlin/in/inmodel/premithus/KavachaVpnService.kt @@ -0,0 +1,335 @@ +package `in`.inmodel.premithus + +import android.content.Intent +import android.net.VpnService +import android.os.ParcelFileDescriptor +import android.util.Log +import java.io.FileInputStream +import java.io.FileOutputStream +import java.net.DatagramPacket +import java.net.DatagramSocket +import java.net.InetAddress + +class KavachaVpnService : VpnService() { + + companion object { + const val ACTION_START = "ACTION_VPN_START" + const val ACTION_STOP = "ACTION_VPN_STOP" + const val CHANNEL = "in.inmodel.premithius/vpn" + var isRunning = false + } + + private var vpnInterface: ParcelFileDescriptor? = null + private var tunnelThread: Thread? = null + private lateinit var domainBlocker: DomainBlocker + + override fun onStartCommand(intent: Intent?, flags: Int, startId: Int): Int { + if (intent?.action == ACTION_STOP) { + stopVpn() + return START_NOT_STICKY + } + if (intent?.action == "ACTION_RELOAD_BLOCKLIST") { + if (::domainBlocker.isInitialized) { + domainBlocker.reload() + } + return START_STICKY + } + if (!isRunning) startVpn() + return START_STICKY + } + + private fun startVpn() { + // Build the TUN interface + val builder = Builder() + .setSession("Premithius Kavacha") + .addAddress("10.0.0.2", 24) + .addDnsServer("10.0.0.1") // our local DNS resolver + .addRoute("0.0.0.0", 0) // route all traffic + .setMtu(1500) + .setBlocking(true) + + // Exclude Premithius itself from VPN + // so our DNS forwarding to 1.1.1.1 is not intercepted + try { + builder.addDisallowedApplication(packageName) + } catch (e: Exception) { + Log.e("KavachaVPN", "Failed to exclude app from VPN: \${e.message}") + } + + vpnInterface = builder.establish() + isRunning = true + + domainBlocker = DomainBlocker(this) + + // Start tunnel on background thread + tunnelThread = Thread { + runTunnel() + }.also { it.start() } + + Log.d("KavachaVPN", "VPN tunnel started") + notifyFlutter("started") + } + + private fun stopVpn() { + isRunning = false + tunnelThread?.interrupt() + try { vpnInterface?.close() } catch (e: Exception) {} + vpnInterface = null + Log.d("KavachaVPN", "VPN tunnel stopped") + notifyFlutter("stopped") + stopSelf() + } + + private fun runTunnel() { + val vpnFd = vpnInterface?.fileDescriptor ?: return + val inputStream = FileInputStream(vpnFd) + val outputStream = FileOutputStream(vpnFd) + + val packet = ByteArray(32767) + + while (isRunning && !Thread.interrupted()) { + try { + // Read incoming IP packet + val length = inputStream.read(packet) + if (length <= 0) continue + + // Parse and handle — focus on DNS (UDP port 53) + val handled = handlePacket(packet, length, outputStream) + + // If not DNS — pass through unchanged + if (!handled) outputStream.write(packet, 0, length) + + } catch (e: InterruptedException) { + break + } catch (e: Exception) { + Log.e("KavachaVPN", "Tunnel error: \${e.message}") + } + } + } + + private fun handlePacket( + packet: ByteArray, + length: Int, + output: FileOutputStream + ): Boolean { + // Check if this is an IP packet (version 4) + if (length < 20) return false + val ipVersion = (packet[0].toInt() shr 4) and 0xF + if (ipVersion != 4) return false + + // Check protocol — 17 = UDP + val protocol = packet[9].toInt() and 0xFF + if (protocol != 17) return false + + // Check destination port — 53 = DNS + val ipHeaderLen = (packet[0].toInt() and 0xF) * 4 + if (length < ipHeaderLen + 8) return false + val destPort = ((packet[ipHeaderLen + 2].toInt() and 0xFF) shl 8) or + (packet[ipHeaderLen + 3].toInt() and 0xFF) + if (destPort != 53) return false + + // Extract DNS query payload + val dnsStart = ipHeaderLen + 8 + val dnsLength = length - dnsStart + if (dnsLength < 12) return false + val dnsPayload = packet.copyOfRange(dnsStart, dnsStart + dnsLength) + + // Parse domain name from DNS query + val domain = parseDnsQuery(dnsPayload) ?: return false + + Log.d("KavachaVPN", "DNS query: \$domain") + + // Check domain against blocklist + val blockResult = domainBlocker.check(domain) + + if (blockResult.isBlocked) { + Log.d("KavachaVPN", "BLOCKED: \$domain — \${blockResult.category}") + + // Return NXDOMAIN response — domain does not exist + val nxDomainResponse = buildNxDomainResponse(packet, length, dnsPayload) + output.write(nxDomainResponse) + + // Log and alert + logBlockedDomain(domain, blockResult) + return true + } + + // Safe domain — forward to 1.1.1.1 and return real answer + val realResponse = forwardDns(dnsPayload, "1.1.1.1") + if (realResponse != null) { + val responsePacket = buildResponsePacket(packet, realResponse) + output.write(responsePacket) + return true + } + + return false + } + + private fun logBlockedDomain(domain: String, result: BlockResult) { + // Log to SQLite (directly into scam_domains + vpn_events) + Thread { + try { + // Assuming path provider defaults for database path + val dbPath = applicationContext.getDatabasePath("premithius.db").absolutePath + val db = android.database.sqlite.SQLiteDatabase.openDatabase(dbPath, null, android.database.sqlite.SQLiteDatabase.OPEN_READWRITE) + + db.execSQL("UPDATE scam_domains SET hit_count = hit_count + 1 WHERE domain = ?", arrayOf(domain)) + + val insertEvent = "INSERT INTO vpn_events (event_type, domain, category, created_at) VALUES (?, ?, ?, ?)" + db.execSQL(insertEvent, arrayOf("blocked", domain, result.category, System.currentTimeMillis())) + + db.close() + } catch (e: Exception) { + Log.e("KavachaVPN", "Failed to log blocked domain to SQLite: \${e.message}") + } + }.start() + + // Fire overlay alert via OverlayService + val intent = Intent(this, OverlayService::class.java) + intent.action = OverlayService.ACTION_SHOW_DOMAIN_BLOCK + intent.putExtra("domain", domain) + intent.putExtra("category", result.category) + startService(intent) + + // Notify Flutter for VPN stats screen + notifyFlutter("blocked:\$domain:\${result.category}") + } + + private fun notifyFlutter(event: String) { + // Store in shared prefs — Flutter polls on resume + // Direct MethodChannel not reliable from background service + getSharedPreferences("vpn_events", MODE_PRIVATE) + .edit() + .putString("last_event", event) + .putLong("last_event_time", System.currentTimeMillis()) + .apply() + } + + override fun onDestroy() { + stopVpn() + super.onDestroy() + } + + // DNS parsing helpers + + private fun parseDnsQuery(payload: ByteArray): String? { + try { + if (payload.size < 12) return null + var pos = 12 // Skip DNS header + val sb = StringBuilder() + while (pos < payload.size) { + val len = payload[pos].toInt() and 0xFF + if (len == 0) break // Root label + if (len >= 192) return null // Pointer, not supporting compressed query parsing + pos++ + if (pos + len > payload.size) return null + for (i in 0 until len) { + sb.append(payload[pos + i].toInt().toChar()) + } + sb.append('.') + pos += len + } + return if (sb.isNotEmpty()) sb.toString().trimEnd('.') else null + } catch (e: Exception) { + return null + } + } + + private fun buildNxDomainResponse(original: ByteArray, len: Int, dns: ByteArray): ByteArray { + val response = ByteArray(len) + System.arraycopy(original, 0, response, 0, len) + + val ipHeaderLen = (response[0].toInt() and 0xF) * 4 + val udpStart = ipHeaderLen + + // IP header: Swap Source and Dest IP + for (i in 0..3) { + val tmp = response[12 + i] + response[12 + i] = response[16 + i] + response[16 + i] = tmp + } + + // UDP header: Swap Source and Dest Port + for (i in 0..1) { + val tmp = response[udpStart + i] + response[udpStart + i] = response[udpStart + 2 + i] + response[udpStart + 2 + i] = tmp + } + + // DNS header: QR=1(response), RCODE=3(NXDOMAIN) + val dnsStart = udpStart + 8 + response[dnsStart + 2] = (response[dnsStart + 2].toInt() or 0x80).toByte() // QR=1 + response[dnsStart + 3] = ((response[dnsStart + 3].toInt() and 0xF0) or 0x03).toByte() + + // Set ANCOUNT=0, NSCOUNT=0, ARCOUNT=0 + response[dnsStart + 6] = 0; response[dnsStart + 7] = 0 + response[dnsStart + 8] = 0; response[dnsStart + 9] = 0 + response[dnsStart + 10] = 0; response[dnsStart + 11] = 0 + + // Clear UDP checksum + response[udpStart + 6] = 0 + response[udpStart + 7] = 0 + + return response + } + + private fun buildResponsePacket(original: ByteArray, dnsResponse: ByteArray): ByteArray { + val ipHeaderLen = (original[0].toInt() and 0xF) * 4 + val udpHeaderLen = 8 + val newLen = ipHeaderLen + udpHeaderLen + dnsResponse.size + val packet = ByteArray(newLen) + + System.arraycopy(original, 0, packet, 0, ipHeaderLen + udpHeaderLen) + System.arraycopy(dnsResponse, 0, packet, ipHeaderLen + udpHeaderLen, dnsResponse.size) + + // IP header Total length + packet[2] = (newLen shr 8).toByte() + packet[3] = (newLen and 0xFF).toByte() + + // Swap IPs + for (i in 0..3) { + val tmp = packet[12 + i] + packet[12 + i] = packet[16 + i] + packet[16 + i] = tmp + } + + // Swap UDP Ports + val udpStart = ipHeaderLen + for (i in 0..1) { + val tmp = packet[udpStart + i] + packet[udpStart + i] = packet[udpStart + 2 + i] + packet[udpStart + 2 + i] = tmp + } + + // UDP Length + val udpLen = udpHeaderLen + dnsResponse.size + packet[udpStart + 4] = (udpLen shr 8).toByte() + packet[udpStart + 5] = (udpLen and 0xFF).toByte() + + // Clear UDP checksum + packet[udpStart + 6] = 0 + packet[udpStart + 7] = 0 + + return packet + } + + private fun forwardDns(query: ByteArray, server: String): ByteArray? { + try { + val socket = DatagramSocket() + socket.soTimeout = 3000 + val address = InetAddress.getByName(server) + val packet = DatagramPacket(query, query.size, address, 53) + socket.send(packet) + + val buf = ByteArray(4096) + val responsePacket = DatagramPacket(buf, buf.size) + socket.receive(responsePacket) + socket.close() + + return buf.copyOfRange(0, responsePacket.length) + } catch (e: Exception) { + Log.e("KavachaVPN", "Forward DNS failed: \${e.message}") + return null + } + } +} diff --git a/android/app/src/main/kotlin/in/inmodel/premithus/KeyboardIMEService.kt b/android/app/src/main/kotlin/in/inmodel/premithus/KeyboardIMEService.kt new file mode 100644 index 0000000000000000000000000000000000000000..ea30a1416c98c9b41fe4eaac330ac000986162dc --- /dev/null +++ b/android/app/src/main/kotlin/in/inmodel/premithus/KeyboardIMEService.kt @@ -0,0 +1,77 @@ +package `in`.inmodel.premithus + +import android.inputmethodservice.InputMethodService +import android.view.View +import android.widget.FrameLayout +import io.flutter.FlutterInjector +import io.flutter.embedding.android.FlutterView +import io.flutter.embedding.engine.FlutterEngine +import io.flutter.embedding.engine.dart.DartExecutor +import io.flutter.plugin.common.MethodChannel + +class KeyboardIMEService : InputMethodService() { + + private lateinit var flutterEngine: FlutterEngine + private lateinit var flutterView: FlutterView + private lateinit var methodChannel: MethodChannel + private val CHANNEL = "in.inmodel.premithus/keyboard" + + override fun onCreate() { + super.onCreate() + + flutterEngine = FlutterEngine(this) + flutterEngine.dartExecutor.executeDartEntrypoint( + DartExecutor.DartEntrypoint( + FlutterInjector.instance().flutterLoader().findAppBundlePath(), + "keyboardMain" + ) + ) + + methodChannel = MethodChannel(flutterEngine.dartExecutor.binaryMessenger, CHANNEL) + methodChannel.setMethodCallHandler { call, result -> + when (call.method) { + "commitText" -> { + val text = call.argument("text") ?: "" + currentInputConnection?.commitText(text, 1) + result.success(null) + } + "deleteBackward" -> { + currentInputConnection?.deleteSurroundingText(1, 0) + result.success(null) + } + "replaceText" -> { + val newText = call.argument("text") ?: "" + currentInputConnection?.deleteSurroundingText(10000, 10000) + currentInputConnection?.commitText(newText, 1) + result.success(null) + } + "getText" -> { + val before = currentInputConnection?.getTextBeforeCursor(5000, 0) ?: "" + val after = currentInputConnection?.getTextAfterCursor(5000, 0) ?: "" + result.success(before.toString() + after.toString()) + } + "hideKeyboard" -> { + requestHideSelf(0) + result.success(null) + } + else -> result.notImplemented() + } + } + } + + override fun onCreateInputView(): View { + flutterView = FlutterView(this) + flutterView.attachToFlutterEngine(flutterEngine) + + // Wrap in FrameLayout to ensure layout bounds + val frameLayout = FrameLayout(this) + frameLayout.addView(flutterView) + return frameLayout + } + + override fun onDestroy() { + flutterView.detachFromFlutterEngine() + flutterEngine.destroy() + super.onDestroy() + } +} diff --git a/android/app/src/main/kotlin/in/inmodel/premithus/LockedAppDao.kt b/android/app/src/main/kotlin/in/inmodel/premithus/LockedAppDao.kt new file mode 100644 index 0000000000000000000000000000000000000000..af1178cc985b940bc37b065c8a5d8d8c01149cc2 --- /dev/null +++ b/android/app/src/main/kotlin/in/inmodel/premithus/LockedAppDao.kt @@ -0,0 +1,43 @@ +package `in`.inmodel.premithus + +import android.content.ContentValues +import android.database.sqlite.SQLiteDatabase + +class LockedAppDao(private val db: SQLiteDatabase) { + + fun isLocked(packageName: String): Boolean { + // Check if app is in locked_apps table AND no active temporary unlock + val cursor = db.rawQuery( + "SELECT temporary_unlock_until FROM locked_apps WHERE package_name = ?", + arrayOf(packageName) + ) + if (!cursor.moveToFirst()) { + cursor.close() + return false + } + val tempUntil = cursor.getLong(0) + cursor.close() + + // If temporary_unlock_until is 0 or in the past, app is locked + return tempUntil == 0L || System.currentTimeMillis() > tempUntil + } + + fun logAccessAttempt(packageName: String, timestamp: Long) { + // Increment access_attempts in locked_apps + db.execSQL( + "UPDATE locked_apps SET access_attempts = access_attempts + 1 WHERE package_name = ?", + arrayOf(packageName) + ) + // Insert into access_log + val values = ContentValues().apply { + put("package_name", packageName) + put("was_allowed", 0) + put("attempted_at", timestamp) + } + try { + db.insert("access_log", null, values) + } catch (e: Exception) { + // Table may not exist yet — ignore + } + } +} diff --git a/android/app/src/main/kotlin/in/inmodel/premithus/MainActivity.kt b/android/app/src/main/kotlin/in/inmodel/premithus/MainActivity.kt new file mode 100644 index 0000000000000000000000000000000000000000..6aea6fdaad914479b5feaa62912aeb367bc0c021 --- /dev/null +++ b/android/app/src/main/kotlin/in/inmodel/premithus/MainActivity.kt @@ -0,0 +1,273 @@ +package `in`.inmodel.premithus + +import android.accessibilityservice.AccessibilityServiceInfo +import android.content.Context +import android.content.pm.ApplicationInfo +import android.content.pm.PackageManager +import android.os.Bundle +import android.view.accessibility.AccessibilityManager +import io.flutter.embedding.android.FlutterActivity +import io.flutter.embedding.engine.FlutterEngine +import io.flutter.plugin.common.MethodChannel +import android.content.Intent +import android.net.VpnService +import android.os.Handler +import android.os.Looper +import org.json.JSONArray +import org.json.JSONObject +import kotlin.concurrent.thread + +class MainActivity : FlutterActivity() { + + companion object { + // Accessibility channel — shared with PremithiusAccessibilityService + var accessibilityChannel: MethodChannel? = null + + // Auth channel — shared with OverlayService + var authChannel: MethodChannel? = null + + const val VPN_REQUEST_CODE = 1001 + var pendingVpnResult: MethodChannel.Result? = null + } + + private val alreadyAlerted = mutableSetOf() + private val sensorMonitorHandler = Handler(Looper.getMainLooper()) + private val sensorMonitorRunnable = object : Runnable { + override fun run() { + thread { + val helper = TelemetryHelper(this@MainActivity) + val active = try { helper.getActiveSensors() } catch(e:Exception){ emptyList() } + for (sensor in active) { + val key = sensor.packageName + sensor.sensor + if (!alreadyAlerted.contains(key)) { + alreadyAlerted.add(key) + val intent = Intent(this@MainActivity, OverlayService::class.java) + intent.action = OverlayService.ACTION_SHOW_SENSOR_ALERT + intent.putExtra("appName", sensor.appName) + intent.putExtra("sensor", sensor.sensor) + intent.putExtra("packageName", sensor.packageName) + startService(intent) + } + } + } + sensorMonitorHandler.postDelayed(this, 60000L) + } + } + + private val clearDedupHandler = Handler(Looper.getMainLooper()) + private val clearDedupRunnable = object : Runnable { + override fun run() { + alreadyAlerted.clear() + clearDedupHandler.postDelayed(this, 600_000L) + } + } + + override fun configureFlutterEngine(flutterEngine: FlutterEngine) { + super.configureFlutterEngine(flutterEngine) + + // ── Accessibility Channel ──────────────────────────────────── + accessibilityChannel = MethodChannel( + flutterEngine.dartExecutor.binaryMessenger, + "in.inmodel.premithius/accessibility" + ).also { channel -> + channel.setMethodCallHandler { call, result -> + when (call.method) { + "isServiceEnabled" -> { + val am = getSystemService(Context.ACCESSIBILITY_SERVICE) as AccessibilityManager + val enabled = am.getEnabledAccessibilityServiceList( + AccessibilityServiceInfo.FEEDBACK_ALL_MASK + ).any { + it.resolveInfo.serviceInfo.packageName == packageName && + it.resolveInfo.serviceInfo.name.contains("PremithiusAccessibilityService") + } + result.success(enabled) + } + "launchApp" -> { + val pkg = call.argument("packageName") + if (pkg != null) { + val intent = packageManager.getLaunchIntentForPackage(pkg) + if (intent != null) startActivity(intent) + } + result.success(null) + } + else -> result.notImplemented() + } + } + } + + // ── Auth Channel ───────────────────────────────────────────── + authChannel = MethodChannel( + flutterEngine.dartExecutor.binaryMessenger, + "in.inmodel.premithius/auth" + ) + // Dart side sets the handler; Kotlin side may invoke methods on it + + // ── Installed Apps Channel ─────────────────────────────────── + MethodChannel( + flutterEngine.dartExecutor.binaryMessenger, + "in.inmodel.premithius/apps" + ).setMethodCallHandler { call, result -> + if (call.method == "getInstalledApps") { + val pm = packageManager + val apps = pm.getInstalledApplications(PackageManager.GET_META_DATA) + .filter { app -> + // Only user-installed apps OR system apps that have a launcher intent + (app.flags and ApplicationInfo.FLAG_SYSTEM) == 0 || + pm.getLaunchIntentForPackage(app.packageName) != null + } + .filter { it.packageName != "in.inmodel.premithus" } + .map { app -> + mapOf( + "packageName" to app.packageName, + "appName" to pm.getApplicationLabel(app).toString() + ) + } + result.success(apps) + } else { + result.notImplemented() + } + } + // ── VPN Channel ────────────────────────────────────────────── + MethodChannel( + flutterEngine.dartExecutor.binaryMessenger, + "in.inmodel.premithius/vpn" + ).setMethodCallHandler { call, result -> + when (call.method) { + "startVpn" -> { + val vpnIntent = VpnService.prepare(this) + if (vpnIntent != null) { + startActivityForResult(vpnIntent, VPN_REQUEST_CODE) + pendingVpnResult = result + } else { + val intent = Intent(this, KavachaVpnService::class.java) + intent.action = KavachaVpnService.ACTION_START + startService(intent) + result.success("started") + } + } + "stopVpn" -> { + val intent = Intent(this, KavachaVpnService::class.java) + intent.action = KavachaVpnService.ACTION_STOP + startService(intent) + result.success("stopped") + } + "getLastEvent" -> { + val prefs = getSharedPreferences("vpn_events", Context.MODE_PRIVATE) + result.success(prefs.getString("last_event", null)) + } + "reloadBlocklist" -> { + val intent = Intent(this, KavachaVpnService::class.java) + intent.action = "ACTION_RELOAD_BLOCKLIST" + startService(intent) + result.success(null) + } + else -> result.notImplemented() + } + } + + // ── Telemetry Channel ───────────────────────────────────────── + MethodChannel( + flutterEngine.dartExecutor.binaryMessenger, + "in.inmodel.premithius/telemetry" + ).setMethodCallHandler { call, result -> + val helper = TelemetryHelper(this@MainActivity) + when (call.method) { + "hasUsagePermission" -> result.success(helper.hasUsageStatsPermission()) + "getPrivacyStories" -> { + thread { + val sensors = try { helper.getActiveSensors() } catch(e:Exception){ emptyList() } + val perms = try { helper.getPermissionStats() } catch(e:Exception){ emptyList() } + val data = try { helper.getSleepTimeDataUsage() } catch(e:Exception){ emptyList() } + val stories = helper.generatePrivacyStories(sensors, perms, data) + val jsonArray = JSONArray() + for (s in stories) { + val obj = JSONObject() + obj.put("severity", s.severity) + obj.put("emoji", s.emoji) + obj.put("english", s.english) + obj.put("hindi", s.hindi) + obj.put("packageName", s.packageName) + jsonArray.put(obj) + } + Handler(Looper.getMainLooper()).post { result.success(jsonArray.toString()) } + } + } + "getActiveSensors" -> { + thread { + val sensors = try { helper.getActiveSensors() } catch(e:Exception){ emptyList() } + val jsonArray = JSONArray() + for (s in sensors) { + val obj = JSONObject() + obj.put("packageName", s.packageName) + obj.put("appName", s.appName) + obj.put("sensor", s.sensor) + obj.put("isActive", s.isActive) + jsonArray.put(obj) + } + Handler(Looper.getMainLooper()).post { result.success(jsonArray.toString()) } + } + } + "getDataUsage" -> { + thread { + val data = try { helper.getSleepTimeDataUsage() } catch(e:Exception){ emptyList() } + val jsonArray = JSONArray() + for (d in data) { + val obj = JSONObject() + obj.put("packageName", d.packageName) + obj.put("appName", d.appName) + obj.put("bytesSent", d.bytesSent) + obj.put("mbSent", d.mbSent) + jsonArray.put(obj) + } + Handler(Looper.getMainLooper()).post { result.success(jsonArray.toString()) } + } + } + "getPermissionStats" -> { + thread { + val perms = try { helper.getPermissionStats() } catch(e:Exception){ emptyList() } + val jsonArray = JSONArray() + for (p in perms) { + val obj = JSONObject() + obj.put("packageName", p.packageName) + obj.put("appName", p.appName) + val counts = JSONObject() + for ((k, v) in p.accessCounts) { counts.put(k, v) } + obj.put("accessCounts", counts) + obj.put("isSystemApp", p.isSystemApp) + jsonArray.put(obj) + } + Handler(Looper.getMainLooper()).post { result.success(jsonArray.toString()) } + } + } + else -> result.notImplemented() + } + } + } + + override fun onActivityResult(requestCode: Int, resultCode: Int, data: Intent?) { + if (requestCode == VPN_REQUEST_CODE) { + if (resultCode == RESULT_OK) { + val intent = Intent(this, KavachaVpnService::class.java) + intent.action = KavachaVpnService.ACTION_START + startService(intent) + pendingVpnResult?.success("started") + } else { + pendingVpnResult?.success("denied") + } + pendingVpnResult = null + } + super.onActivityResult(requestCode, resultCode, data) + } + + override fun onCreate(savedInstanceState: Bundle?) { + super.onCreate(savedInstanceState) + sensorMonitorHandler.post(sensorMonitorRunnable) + clearDedupHandler.postDelayed(clearDedupRunnable, 600000L) + } + + override fun onDestroy() { + super.onDestroy() + sensorMonitorHandler.removeCallbacksAndMessages(null) + clearDedupHandler.removeCallbacksAndMessages(null) + } +} diff --git a/android/app/src/main/kotlin/in/inmodel/premithus/OverlayService.kt b/android/app/src/main/kotlin/in/inmodel/premithus/OverlayService.kt new file mode 100644 index 0000000000000000000000000000000000000000..743a95d14695d7c2aa7dae0cc26032f57c2535c9 --- /dev/null +++ b/android/app/src/main/kotlin/in/inmodel/premithus/OverlayService.kt @@ -0,0 +1,515 @@ +package `in`.inmodel.premithus + +import android.app.Service +import android.content.Context +import android.content.Intent +import android.graphics.Color +import android.graphics.PixelFormat +import android.os.Handler +import android.os.IBinder +import android.os.Looper +import android.view.Gravity +import android.view.ViewGroup +import android.view.WindowManager +import android.widget.Button +import android.widget.LinearLayout +import android.widget.TextView +import io.flutter.FlutterInjector +import io.flutter.embedding.engine.FlutterEngine +import io.flutter.embedding.engine.dart.DartExecutor +import io.flutter.plugin.common.MethodChannel + +class OverlayService : Service() { + + companion object { + const val ACTION_SHOW_AUTH = "ACTION_SHOW_AUTH" + const val ACTION_SHOW_DOMAIN_BLOCK = "ACTION_SHOW_DOMAIN_BLOCK" + const val ACTION_SHOW_SENSOR_ALERT = "ACTION_SHOW_SENSOR_ALERT" + } + + private lateinit var windowManager: WindowManager + private var overlayView: LinearLayout? = null + private var authOverlayView: LinearLayout? = null + private var autoDismissHandler: Handler? = null + + // Background single engine for scam analysis + private lateinit var flutterEngine: FlutterEngine + private lateinit var methodChannel: MethodChannel + private val CHANNEL = "in.inmodel.premithus/scam" + + override fun onCreate() { + super.onCreate() + windowManager = getSystemService(Context.WINDOW_SERVICE) as WindowManager + + flutterEngine = FlutterEngine(this) + flutterEngine.dartExecutor.executeDartEntrypoint( + DartExecutor.DartEntrypoint( + FlutterInjector.instance().flutterLoader().findAppBundlePath(), + "scamMain" + ) + ) + methodChannel = MethodChannel(flutterEngine.dartExecutor.binaryMessenger, CHANNEL) + } + + override fun onStartCommand(intent: Intent?, flags: Int, startId: Int): Int { + if (intent?.action == "in.inmodel.premithus.ACTION_ANALYZE_SMS") { + val sender = intent.getStringExtra("sender") ?: "" + val messageBody = intent.getStringExtra("messageBody") ?: "" + + val params = mapOf("sender" to sender, "messageBody" to messageBody) + + methodChannel.invokeMethod("analyze", params, object : MethodChannel.Result { + override fun success(result: Any?) { + val map = result as? Map ?: return + val isScam = map["isScam"] as? Boolean ?: false + val category = map["category"] as? String ?: "Unknown" + val layerLabel = map["layerLabel"] as? String ?: "" + if (isScam) { + showOverlay(sender, messageBody, category, layerLabel) + } + } + override fun error(errorCode: String, errorMessage: String?, errorDetails: Any?) {} + override fun notImplemented() {} + }) + } + + if (intent?.action == ACTION_SHOW_AUTH) { + val packageName = intent.getStringExtra("package_name") ?: return START_STICKY + val appName = intent.getStringExtra("app_name") ?: packageName + showAuthOverlay(packageName, appName) + } + + if (intent?.action == ACTION_SHOW_DOMAIN_BLOCK) { + val domain = intent.getStringExtra("domain") ?: "" + val category = intent.getStringExtra("category") ?: "" + showDomainBlockOverlay(domain, category) + } + + if (intent?.action == ACTION_SHOW_SENSOR_ALERT) { + val appName = intent.getStringExtra("appName") ?: "" + val sensor = intent.getStringExtra("sensor") ?: "" + val packageName = intent.getStringExtra("packageName") ?: "" + showSensorOverlay(appName, sensor, packageName) + } + + return START_STICKY + } + + private fun showAuthOverlay(packageName: String, appName: String) { + // Dismiss any existing auth overlay + authOverlayView?.let { + try { windowManager.removeView(it) } catch (e: Exception) {} + } + autoDismissHandler?.removeCallbacksAndMessages(null) + + authOverlayView = LinearLayout(this).apply { + orientation = LinearLayout.VERTICAL + setBackgroundColor(android.graphics.Color.parseColor("#1A1A2E")) + setPadding(40, 48, 40, 48) + + val titleView = android.widget.TextView(context).apply { + text = "\uD83D\uDD12 App Locked — $appName" + setTextColor(android.graphics.Color.WHITE) + textSize = 18f + setTypeface(null, android.graphics.Typeface.BOLD) + } + addView(titleView) + + val subtitleView = android.widget.TextView(context).apply { + text = "Authenticate to open" + setTextColor(android.graphics.Color.parseColor("#AAAACC")) + textSize = 14f + setPadding(0, 8, 0, 24) + } + addView(subtitleView) + + val buttonLayout = LinearLayout(context).apply { + orientation = LinearLayout.HORIZONTAL + + val biometricBtn = android.widget.Button(context).apply { + text = "Use Biometrics" + setTextColor(android.graphics.Color.WHITE) + setBackgroundColor(android.graphics.Color.parseColor("#6C63FF")) + layoutParams = LinearLayout.LayoutParams( + 0, android.view.ViewGroup.LayoutParams.WRAP_CONTENT, 1f + ).apply { setMargins(0, 0, 8, 0) } + setOnClickListener { + // Send biometric auth request to Flutter via MainActivity channel + Handler(Looper.getMainLooper()).post { + val args = mapOf("packageName" to packageName, "appName" to appName) + MainActivity.authChannel?.invokeMethod("requestBiometricAuth", args) + } + dismissAuthOverlay() + } + } + + val cancelBtn = android.widget.Button(context).apply { + text = "Cancel" + setTextColor(android.graphics.Color.WHITE) + setBackgroundColor(android.graphics.Color.parseColor("#444466")) + layoutParams = LinearLayout.LayoutParams( + 0, android.view.ViewGroup.LayoutParams.WRAP_CONTENT, 1f + ).apply { setMargins(8, 0, 0, 0) } + setOnClickListener { dismissAuthOverlay() } + } + + addView(biometricBtn) + addView(cancelBtn) + } + addView(buttonLayout) + } + + val params = android.view.WindowManager.LayoutParams( + android.view.WindowManager.LayoutParams.MATCH_PARENT, + android.view.WindowManager.LayoutParams.WRAP_CONTENT, + android.view.WindowManager.LayoutParams.TYPE_APPLICATION_OVERLAY, + android.view.WindowManager.LayoutParams.FLAG_NOT_TOUCH_MODAL, + android.graphics.PixelFormat.TRANSLUCENT + ).apply { + gravity = android.view.Gravity.TOP + y = 100 + } + + windowManager.addView(authOverlayView, params) + + // Auto dismiss after 15 seconds + autoDismissHandler = Handler(Looper.getMainLooper()) + autoDismissHandler!!.postDelayed({ dismissAuthOverlay() }, 15_000) + } + + private fun dismissAuthOverlay() { + autoDismissHandler?.removeCallbacksAndMessages(null) + authOverlayView?.let { + try { windowManager.removeView(it) } catch (e: Exception) {} + authOverlayView = null + } + } + + private fun showOverlay(sender: String, message: String, category: String, layerLabel: String = "") { + if (overlayView != null) { + windowManager.removeView(overlayView) + } + + overlayView = LinearLayout(this).apply { + orientation = LinearLayout.VERTICAL + setBackgroundColor(Color.parseColor("#E53935")) // Red background + setPadding(32, 32, 32, 32) + + val titleView = TextView(context).apply { + text = "HIGH RISK — $category" + setTextColor(Color.WHITE) + textSize = 18f + setTypeface(null, android.graphics.Typeface.BOLD) + } + + val previewView = TextView(context).apply { + text = "$sender: ${message.take(60)}..." + setTextColor(Color.WHITE) + textSize = 14f + setPadding(0, 8, 0, 0) + } + + addView(titleView) + + if (layerLabel.isNotEmpty()) { + val caughtByView = TextView(context).apply { + text = "\uD83D\uDEE1\uFE0F Caught by: $layerLabel" + setTextColor(Color.parseColor("#FFCDD2")) + textSize = 12f + setPadding(0, 4, 0, 0) + } + addView(caughtByView) + } + addView(previewView) + + val buttonLayout = LinearLayout(context).apply { + orientation = LinearLayout.HORIZONTAL + setPadding(0, 32, 0, 0) + + val confirmBtn = Button(context).apply { + text = "Confirm Scam" + setTextColor(Color.WHITE) + setBackgroundColor(Color.parseColor("#B71C1C")) + layoutParams = LinearLayout.LayoutParams(0, ViewGroup.LayoutParams.WRAP_CONTENT, 1f).apply { + setMargins(0, 0, 8, 0) + } + setOnClickListener { + val params = mapOf("sender" to sender, "messageBody" to message, "isScam" to true) + methodChannel.invokeMethod("feedback", params) + windowManager.removeView(overlayView) + overlayView = null + } + } + + val safeBtn = Button(context).apply { + text = "Not a Scam" + setTextColor(Color.WHITE) + setBackgroundColor(Color.parseColor("#43A047")) + layoutParams = LinearLayout.LayoutParams(0, ViewGroup.LayoutParams.WRAP_CONTENT, 1f).apply { + setMargins(8, 0, 0, 0) + } + setOnClickListener { + val params = mapOf("sender" to sender, "messageBody" to message, "isScam" to false) + methodChannel.invokeMethod("feedback", params) + windowManager.removeView(overlayView) + overlayView = null + } + } + + addView(confirmBtn) + addView(safeBtn) + } + addView(buttonLayout) + + setOnClickListener { + windowManager.removeView(overlayView) + overlayView = null + } + } + + val params = WindowManager.LayoutParams( + WindowManager.LayoutParams.MATCH_PARENT, + WindowManager.LayoutParams.WRAP_CONTENT, + WindowManager.LayoutParams.TYPE_APPLICATION_OVERLAY, + WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE or WindowManager.LayoutParams.FLAG_NOT_TOUCH_MODAL, + PixelFormat.TRANSLUCENT + ).apply { + gravity = Gravity.TOP + y = 50 // small inset + } + + windowManager.addView(overlayView, params) + + // Auto dismiss after 8 seconds + Handler(Looper.getMainLooper()).postDelayed({ + if (overlayView != null) { + windowManager.removeView(overlayView) + overlayView = null + } + }, 8000) + + // Force widget refresh whenever a scam SMS is detected + try { + PremithiusWidget.forceRefresh(applicationContext) + } catch(e: Exception) {} + } + + private fun showDomainBlockOverlay(domain: String, category: String) { + if (overlayView != null) { + windowManager.removeView(overlayView) + } + + overlayView = LinearLayout(this).apply { + orientation = LinearLayout.VERTICAL + setBackgroundColor(Color.parseColor("#E53935")) // Red background + setPadding(32, 32, 32, 32) + + val titleView = TextView(context).apply { + text = "Scam Domain Blocked" + setTextColor(Color.WHITE) + textSize = 18f + setTypeface(null, android.graphics.Typeface.BOLD) + } + + val caughtByView = TextView(context).apply { + text = "\uD83D\uDEE1\uFE0F Caught by: Kavacha VPN Shield" + setTextColor(Color.parseColor("#FFCDD2")) + textSize = 12f + setPadding(0, 4, 0, 8) + } + + val subtitleView = TextView(context).apply { + text = domain + setTextColor(Color.WHITE) + textSize = 16f + setTypeface(null, android.graphics.Typeface.BOLD) + } + + val detailView = TextView(context).apply { + text = category + setTextColor(Color.parseColor("#FFCDD2")) + textSize = 14f + setPadding(0, 4, 0, 0) + } + + addView(titleView) + addView(caughtByView) + addView(subtitleView) + addView(detailView) + + val buttonLayout = LinearLayout(context).apply { + orientation = LinearLayout.HORIZONTAL + setPadding(0, 32, 0, 0) + + val detailsBtn = Button(context).apply { + text = "View Details" + setTextColor(Color.WHITE) + setBackgroundColor(Color.parseColor("#B71C1C")) + layoutParams = LinearLayout.LayoutParams(0, ViewGroup.LayoutParams.WRAP_CONTENT, 1f).apply { + setMargins(0, 0, 8, 0) + } + setOnClickListener { + val launchIntent = packageManager.getLaunchIntentForPackage(packageName) + if (launchIntent != null) { + launchIntent.flags = Intent.FLAG_ACTIVITY_NEW_TASK or Intent.FLAG_ACTIVITY_CLEAR_TOP + startActivity(launchIntent) + } + windowManager.removeView(overlayView) + overlayView = null + } + } + + val dismissBtn = Button(context).apply { + text = "Dismiss" + setTextColor(Color.WHITE) + setBackgroundColor(Color.parseColor("#444466")) + layoutParams = LinearLayout.LayoutParams(0, ViewGroup.LayoutParams.WRAP_CONTENT, 1f).apply { + setMargins(8, 0, 0, 0) + } + setOnClickListener { + windowManager.removeView(overlayView) + overlayView = null + } + } + + addView(detailsBtn) + addView(dismissBtn) + } + addView(buttonLayout) + } + + val params = WindowManager.LayoutParams( + WindowManager.LayoutParams.MATCH_PARENT, + WindowManager.LayoutParams.WRAP_CONTENT, + WindowManager.LayoutParams.TYPE_APPLICATION_OVERLAY, + WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE or WindowManager.LayoutParams.FLAG_NOT_TOUCH_MODAL, + PixelFormat.TRANSLUCENT + ).apply { + gravity = Gravity.TOP + y = 50 // small inset + } + + windowManager.addView(overlayView, params) + + // Auto dismiss after 6 seconds + Handler(Looper.getMainLooper()).postDelayed({ + if (overlayView != null) { + windowManager.removeView(overlayView) + overlayView = null + } + }, 6000) + + // Force widget refresh whenever a domain is blocked + try { + PremithiusWidget.forceRefresh(applicationContext) + } catch(e: Exception) {} + } + + private fun showSensorOverlay(appName: String, sensor: String, packageName: String) { + if (overlayView != null) { + windowManager.removeView(overlayView) + } + + overlayView = LinearLayout(this).apply { + orientation = LinearLayout.VERTICAL + setBackgroundColor(Color.parseColor("#FFCC7700")) // Orange background for sensor alert + setPadding(32, 32, 32, 32) + + val titleView = TextView(context).apply { + text = "${sensor.capitalize()} active in background" + setTextColor(Color.WHITE) + textSize = 18f + setTypeface(null, android.graphics.Typeface.BOLD) + } + + val caughtByView = TextView(context).apply { + text = "\uD83D\uDEE1\uFE0F Caught by: Data Shield" + setTextColor(Color.parseColor("#FFE0B2")) + textSize = 12f + setPadding(0, 4, 0, 8) + } + + val subtitleView = TextView(context).apply { + text = "$appName is using your $sensor right now" + setTextColor(Color.WHITE) + textSize = 16f + } + + addView(titleView) + addView(caughtByView) + addView(subtitleView) + + val buttonLayout = LinearLayout(context).apply { + orientation = LinearLayout.HORIZONTAL + setPadding(0, 32, 0, 0) + + val detailsBtn = Button(context).apply { + text = "Open Data Shield" + setTextColor(Color.WHITE) + setBackgroundColor(Color.parseColor("#E65100")) + layoutParams = LinearLayout.LayoutParams(0, ViewGroup.LayoutParams.WRAP_CONTENT, 1f).apply { + setMargins(0, 0, 8, 0) + } + setOnClickListener { + val launchIntent = packageManager.getLaunchIntentForPackage(context.packageName) + if (launchIntent != null) { + launchIntent.flags = Intent.FLAG_ACTIVITY_NEW_TASK or Intent.FLAG_ACTIVITY_CLEAR_TOP + startActivity(launchIntent) + } + windowManager.removeView(overlayView) + overlayView = null + } + } + + val dismissBtn = Button(context).apply { + text = "Dismiss" + setTextColor(Color.WHITE) + setBackgroundColor(Color.parseColor("#444466")) + layoutParams = LinearLayout.LayoutParams(0, ViewGroup.LayoutParams.WRAP_CONTENT, 1f).apply { + setMargins(8, 0, 0, 0) + } + setOnClickListener { + windowManager.removeView(overlayView) + overlayView = null + } + } + + addView(detailsBtn) + addView(dismissBtn) + } + addView(buttonLayout) + } + + val params = WindowManager.LayoutParams( + WindowManager.LayoutParams.MATCH_PARENT, + WindowManager.LayoutParams.WRAP_CONTENT, + WindowManager.LayoutParams.TYPE_APPLICATION_OVERLAY, + WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE or WindowManager.LayoutParams.FLAG_NOT_TOUCH_MODAL, + PixelFormat.TRANSLUCENT + ).apply { + gravity = Gravity.TOP + y = 50 // small inset + } + + windowManager.addView(overlayView, params) + + // Auto dismiss after 8 seconds + Handler(Looper.getMainLooper()).postDelayed({ + if (overlayView != null) { + windowManager.removeView(overlayView) + overlayView = null + } + }, 8000) + } + + override fun onBind(intent: Intent?): IBinder? = null + + override fun onDestroy() { + super.onDestroy() + flutterEngine.destroy() + if (overlayView != null) { + try { windowManager.removeView(overlayView) } catch (e: Exception) {} + } + dismissAuthOverlay() + } +} diff --git a/android/app/src/main/kotlin/in/inmodel/premithus/PremithiusAccessibilityService.kt b/android/app/src/main/kotlin/in/inmodel/premithus/PremithiusAccessibilityService.kt new file mode 100644 index 0000000000000000000000000000000000000000..f0b6538b83a88a08bb23a3fdffdbafad1be2e7a9 --- /dev/null +++ b/android/app/src/main/kotlin/in/inmodel/premithus/PremithiusAccessibilityService.kt @@ -0,0 +1,135 @@ +package `in`.inmodel.premithus + +import android.accessibilityservice.AccessibilityService +import android.accessibilityservice.AccessibilityServiceInfo +import android.content.Intent +import android.os.Handler +import android.os.Looper +import android.util.Log +import android.view.accessibility.AccessibilityEvent + +class PremithiusAccessibilityService : AccessibilityService() { + + companion object { + // Shared state — readable from other Kotlin classes + var foregroundPackage: String = "" + var foregroundAppName: String = "" + var isServiceRunning: Boolean = false + + // MethodChannel name for Flutter communication + const val CHANNEL = "in.inmodel.premithius/accessibility" + } + + override fun onServiceConnected() { + isServiceRunning = true + // Configure which events to listen for + val info = AccessibilityServiceInfo() + info.eventTypes = AccessibilityEvent.TYPE_WINDOW_STATE_CHANGED or + AccessibilityEvent.TYPE_WINDOW_CONTENT_CHANGED + info.feedbackType = AccessibilityServiceInfo.FEEDBACK_GENERIC + info.flags = AccessibilityServiceInfo.FLAG_REPORT_VIEW_IDS or + AccessibilityServiceInfo.FLAG_RETRIEVE_INTERACTIVE_WINDOWS + info.notificationTimeout = 100 + serviceInfo = info + Log.d("PremithiusA11y", "Service connected") + } + + override fun onAccessibilityEvent(event: AccessibilityEvent) { + if (event.eventType != AccessibilityEvent.TYPE_WINDOW_STATE_CHANGED) return + + val packageName = event.packageName?.toString() ?: return + if (packageName == foregroundPackage) return // same app, ignore + if (packageName == "in.inmodel.premithus") return // ignore ourselves + + foregroundPackage = packageName + foregroundAppName = getAppName(packageName) + + Log.d("PremithiusA11y", "Foreground: $packageName") + + // Feature 1: App Lock check + checkAppLock(packageName) + + // Feature 2: Notify Flutter of foreground context + // (used by keyboard tone switching + OTP verification) + notifyFlutter(packageName, foregroundAppName) + } + + override fun onInterrupt() { + isServiceRunning = false + } + + // ── Feature 1: App Lock ────────────────────────────────────── + private fun checkAppLock(packageName: String) { + // Query locked_apps SQLite table via PremithiusDatabase + // Run on background thread — never block accessibility thread + Thread { + val isLocked = PremithiusDatabase.getInstance(this) + .lockedAppDao() + .isLocked(packageName) + + if (isLocked) { + Log.d("PremithiusA11y", "LOCKED APP DETECTED: $packageName") + + // Step 1: Immediately go home — app never shows + performGlobalAction(GLOBAL_ACTION_HOME) + + // Step 2: Show auth overlay via OverlayService + val intent = Intent(this, OverlayService::class.java) + intent.action = OverlayService.ACTION_SHOW_AUTH + intent.putExtra("package_name", packageName) + intent.putExtra("app_name", foregroundAppName) + startService(intent) + + // Step 3: Log access attempt + PremithiusDatabase.getInstance(this) + .lockedAppDao() + .logAccessAttempt(packageName, System.currentTimeMillis()) + } + }.start() + } + + // ── Feature 2: Notify Flutter ──────────────────────────────── + private fun notifyFlutter(packageName: String, appName: String) { + // Send foreground context to Flutter via MethodChannel + val context = mapOf( + "package" to packageName, + "appName" to appName, + "toneContext" to getToneContext(packageName) + ) + // Post to main thread for MethodChannel call + Handler(Looper.getMainLooper()).post { + MainActivity.accessibilityChannel?.invokeMethod("onForegroundChanged", context) + } + } + + // ── Tone context mapping ───────────────────────────────────── + private fun getToneContext(packageName: String): String { + return when { + packageName.contains("whatsapp") || + packageName.contains("telegram") || + packageName.contains("signal") -> "casual" + + packageName.contains("gmail") || + packageName.contains("outlook") || + packageName.contains("yahoo.mail") -> "formal" + + packageName.contains("linkedin") -> "professional" + + packageName.contains("twitter") || + packageName.contains("instagram") -> "casual" + + else -> "neutral" + } + } + + // ── Helper: get human-readable app name ───────────────────── + private fun getAppName(packageName: String): String { + return try { + val pm = packageManager + val appInfo = pm.getApplicationInfo(packageName, 0) + pm.getApplicationLabel(appInfo).toString() + } catch (e: Exception) { + packageName + } + } +} diff --git a/android/app/src/main/kotlin/in/inmodel/premithus/PremithiusDatabase.kt b/android/app/src/main/kotlin/in/inmodel/premithus/PremithiusDatabase.kt new file mode 100644 index 0000000000000000000000000000000000000000..f194e51963a0618bfefa63d94df084e5e4e16f5c --- /dev/null +++ b/android/app/src/main/kotlin/in/inmodel/premithus/PremithiusDatabase.kt @@ -0,0 +1,99 @@ +package `in`.inmodel.premithus + +import android.content.Context +import android.database.sqlite.SQLiteDatabase +import android.database.sqlite.SQLiteOpenHelper + +class PremithiusDatabase private constructor(context: Context) + : SQLiteOpenHelper(context, "premithius.db", null, 2) { + + companion object { + @Volatile private var INSTANCE: PremithiusDatabase? = null + + fun getInstance(context: Context): PremithiusDatabase { + return INSTANCE ?: synchronized(this) { + INSTANCE ?: PremithiusDatabase(context.applicationContext).also { INSTANCE = it } + } + } + } + + override fun onCreate(db: SQLiteDatabase) { + // Tables created by Flutter (sqflite) — we just add new ones here + db.execSQL(""" + CREATE TABLE IF NOT EXISTS locked_apps ( + id INTEGER PRIMARY KEY AUTOINCREMENT, + package_name TEXT UNIQUE NOT NULL, + app_name TEXT NOT NULL, + auth_method TEXT DEFAULT 'biometric', + locked_at INTEGER NOT NULL, + access_attempts INTEGER DEFAULT 0, + temporary_unlock_until INTEGER DEFAULT 0 + ) + """.trimIndent()) + + db.execSQL(""" + CREATE TABLE IF NOT EXISTS access_log ( + id INTEGER PRIMARY KEY AUTOINCREMENT, + package_name TEXT NOT NULL, + app_name TEXT, + was_allowed INTEGER DEFAULT 0, + attempted_at INTEGER NOT NULL + ) + """.trimIndent()) + } + + override fun onUpgrade(db: SQLiteDatabase, oldVersion: Int, newVersion: Int) { + if (oldVersion < 2) { + db.execSQL(""" + CREATE TABLE IF NOT EXISTS locked_apps ( + id INTEGER PRIMARY KEY AUTOINCREMENT, + package_name TEXT UNIQUE NOT NULL, + app_name TEXT NOT NULL, + auth_method TEXT DEFAULT 'biometric', + locked_at INTEGER NOT NULL, + access_attempts INTEGER DEFAULT 0, + temporary_unlock_until INTEGER DEFAULT 0 + ) + """.trimIndent()) + + db.execSQL(""" + CREATE TABLE IF NOT EXISTS access_log ( + id INTEGER PRIMARY KEY AUTOINCREMENT, + package_name TEXT NOT NULL, + app_name TEXT, + was_allowed INTEGER DEFAULT 0, + attempted_at INTEGER NOT NULL + ) + """.trimIndent()) + } + } + + fun lockedAppDao(): LockedAppDao = LockedAppDao(writableDatabase) + + fun scamLogDao() = ScamLogDao(writableDatabase) + fun scamDomainDao() = ScamDomainDao(writableDatabase) + + class ScamLogDao(private val db: SQLiteDatabase) { + fun getCountSince(timestamp: Long): Int { + val cursor = db.rawQuery("SELECT COUNT(*) FROM scam_log WHERE created_at >= ?", arrayOf(timestamp.toString())) + var count = 0 + if (cursor.moveToFirst()) { + count = cursor.getInt(0) + } + cursor.close() + return count + } + } + + class ScamDomainDao(private val db: SQLiteDatabase) { + fun getHitsSince(timestamp: Long): Int { + val cursor = db.rawQuery("SELECT COUNT(*) FROM vpn_events WHERE created_at >= ?", arrayOf(timestamp.toString())) + var count = 0 + if (cursor.moveToFirst()) { + count = cursor.getInt(0) + } + cursor.close() + return count + } + } +} diff --git a/android/app/src/main/kotlin/in/inmodel/premithus/PremithiusWidget.kt b/android/app/src/main/kotlin/in/inmodel/premithus/PremithiusWidget.kt new file mode 100644 index 0000000000000000000000000000000000000000..a357abc41c4a6899505a39ca4add304f856e8cfd --- /dev/null +++ b/android/app/src/main/kotlin/in/inmodel/premithus/PremithiusWidget.kt @@ -0,0 +1,97 @@ +package `in`.inmodel.premithus + +import android.app.PendingIntent +import android.appwidget.AppWidgetManager +import android.appwidget.AppWidgetProvider +import android.content.ComponentName +import android.content.Context +import android.content.Intent +import android.widget.RemoteViews + +class PremithiusWidget : AppWidgetProvider() { + + override fun onUpdate( + context: Context, + appWidgetManager: AppWidgetManager, + appWidgetIds: IntArray + ) { + appWidgetIds.forEach { id -> + updateWidget(context, appWidgetManager, id) + } + } + + companion object { + fun updateWidget(context: Context, manager: AppWidgetManager, id: Int) { + val views = RemoteViews(context.packageName, R.layout.widget_layout) + + // Read data from SQLite directly (no Flutter needed) + val db = PremithiusDatabase.getInstance(context) + val today = System.currentTimeMillis() - 86400000L + + // Tile 1: Mic/Camera RIGHT NOW + val telemetry = TelemetryHelper(context) + val activeSensors = try { telemetry.getActiveSensors() } catch (e: Exception) { emptyList() } + val sensorText = if (activeSensors.isNotEmpty()) + "⚠️ ${activeSensors.first().appName} active" + else "✅ No sensors active" + val sensorColor = if (activeSensors.isNotEmpty()) + R.color.widget_red else R.color.widget_green + views.setTextViewText(R.id.tile_sensor, sensorText) + views.setInt(R.id.tile_sensor, "setBackgroundColor", + context.getColor(sensorColor)) + + // Tile 2: Data sent last night (MB) + val dataUsage = try { telemetry.getSleepTimeDataUsage() } catch (e: Exception) { emptyList() } + val totalMb = dataUsage.sumOf { it.mbSent }.toInt() + val dataText = if (totalMb > 0) "📤 ${totalMb}MB sent" else "📤 0MB sent" + val dataColor = if (totalMb > 100) R.color.widget_red + else if (totalMb > 20) R.color.widget_amber + else R.color.widget_green + views.setTextViewText(R.id.tile_data, dataText) + views.setInt(R.id.tile_data, "setBackgroundColor", + context.getColor(dataColor)) + + // Tile 3: Suspicious permission spikes today + val permStats = try { telemetry.getPermissionStats(1) } catch (e: Exception) { emptyList() } + val spikeCount = permStats.count { it.totalAccesses > 5 } + val spikeText = if (spikeCount > 0) "⚠️ $spikeCount app spikes" else "✅ No spikes" + val spikeColor = if (spikeCount > 0) R.color.widget_amber else R.color.widget_green + views.setTextViewText(R.id.tile_perms, spikeText) + views.setInt(R.id.tile_perms, "setBackgroundColor", + context.getColor(spikeColor)) + + // Tile 4: Scam SMS + Domains blocked today (combined) + val scamCount = try { db.scamLogDao().getCountSince(today) } catch(e:Exception){ 0 } + val domainCount = try { db.scamDomainDao().getHitsSince(today) } catch(e:Exception){ 0 } + val totalBlocked = scamCount + domainCount + val blockedText = if (totalBlocked > 0) + "🚨 $totalBlocked blocked" else "✅ 0 blocked" + val blockedColor = if (totalBlocked > 0) R.color.widget_red else R.color.widget_green + views.setTextViewText(R.id.tile_blocked, blockedText) + views.setInt(R.id.tile_blocked, "setBackgroundColor", + context.getColor(blockedColor)) + + // Tap widget → open Premithius app + val launchIntent = context.packageManager.getLaunchIntentForPackage(context.packageName) + if (launchIntent != null) { + val pendingIntent = PendingIntent.getActivity( + context, 0, + launchIntent, + PendingIntent.FLAG_IMMUTABLE + ) + views.setOnClickPendingIntent(R.id.widget_root, pendingIntent) + } + + manager.updateAppWidget(id, views) + } + + fun forceRefresh(context: Context) { + val intent = Intent(context, PremithiusWidget::class.java) + intent.action = AppWidgetManager.ACTION_APPWIDGET_UPDATE + val ids = AppWidgetManager.getInstance(context) + .getAppWidgetIds(ComponentName(context, PremithiusWidget::class.java)) + intent.putExtra(AppWidgetManager.EXTRA_APPWIDGET_IDS, ids) + context.sendBroadcast(intent) + } + } +} diff --git a/android/app/src/main/kotlin/in/inmodel/premithus/SmsReceiver.kt b/android/app/src/main/kotlin/in/inmodel/premithus/SmsReceiver.kt new file mode 100644 index 0000000000000000000000000000000000000000..50b62e37a217f801136658629726c912af9519ff --- /dev/null +++ b/android/app/src/main/kotlin/in/inmodel/premithus/SmsReceiver.kt @@ -0,0 +1,26 @@ +package `in`.inmodel.premithus + +import android.content.BroadcastReceiver +import android.content.Context +import android.content.Intent +import android.provider.Telephony + +class SmsReceiver : BroadcastReceiver() { + override fun onReceive(context: Context, intent: Intent) { + if (intent.action == Telephony.Sms.Intents.SMS_RECEIVED_ACTION) { + val messages = Telephony.Sms.Intents.getMessagesFromIntent(intent) + for (sms in messages) { + val sender = sms.displayOriginatingAddress + val messageBody = sms.messageBody + + // Start OverlayService to analyze SMS using Flutter + val serviceIntent = Intent(context, OverlayService::class.java).apply { + putExtra("sender", sender) + putExtra("messageBody", messageBody) + action = "in.inmodel.premithus.ACTION_ANALYZE_SMS" + } + context.startService(serviceIntent) + } + } + } +} diff --git a/android/app/src/main/kotlin/in/inmodel/premithus/TelemetryHelper.kt b/android/app/src/main/kotlin/in/inmodel/premithus/TelemetryHelper.kt new file mode 100644 index 0000000000000000000000000000000000000000..a2bb18216f96dbbe0fd4f7e1d3817913a7dce137 --- /dev/null +++ b/android/app/src/main/kotlin/in/inmodel/premithus/TelemetryHelper.kt @@ -0,0 +1,251 @@ +package `in`.inmodel.premithus + +import android.app.AppOpsManager +import android.app.usage.NetworkStats +import android.app.usage.NetworkStatsManager +import android.app.usage.UsageStatsManager +import android.content.Context +import android.content.pm.ApplicationInfo +import android.content.pm.PackageManager +import android.net.ConnectivityManager +import android.util.Log + +class TelemetryHelper(private val context: Context) { + + // ── Mic/Camera real-time access ───────────────────────────── + fun getActiveSensors(): List { + val appOps = context.getSystemService(AppOpsManager::class.java) + val result = mutableListOf() + + val packages = context.packageManager + .getInstalledApplications(PackageManager.GET_META_DATA) + + for (app in packages) { + val micOp = appOps.unsafeCheckOpNoThrow( + AppOpsManager.OPSTR_RECORD_AUDIO, + app.uid, app.packageName + ) + val camOp = appOps.unsafeCheckOpNoThrow( + AppOpsManager.OPSTR_CAMERA, + app.uid, app.packageName + ) + + // MODE_RUNNING = currently active (Android 10+) + if (micOp == AppOpsManager.MODE_RUNNING) { + result.add(SensorAccess(app.packageName, + getAppName(app.packageName), "microphone", true)) + } + if (camOp == AppOpsManager.MODE_RUNNING) { + result.add(SensorAccess(app.packageName, + getAppName(app.packageName), "camera", true)) + } + } + return result + } + + // ── Permission access counts (last 7 days) ────────────────── + fun getPermissionStats(days: Int = 7): List { + val appOps = context.getSystemService(AppOpsManager::class.java) + val result = mutableListOf() + val since = System.currentTimeMillis() - (days * 86400000L) + + val ops = listOf( + AppOpsManager.OPSTR_RECORD_AUDIO to "microphone", + AppOpsManager.OPSTR_CAMERA to "camera", + AppOpsManager.OPSTR_FINE_LOCATION to "location", + AppOpsManager.OPSTR_READ_CONTACTS to "contacts", + AppOpsManager.OPSTR_READ_SMS to "SMS" + ) + + val packages = context.packageManager + .getInstalledApplications(PackageManager.GET_META_DATA) + + for (app in packages) { + val stats = mutableMapOf() + for ((opStr, label) in ops) { + try { + val pkgOps = appOps.getOpsForPackage( + app.uid, app.packageName, arrayOf(opStr) + ) + val count = pkgOps?.firstOrNull()?.ops + ?.filter { it.time > since } + ?.size ?: 0 + if (count > 0) stats[label] = count + } catch (e: Exception) { /* skip */ } + } + if (stats.isNotEmpty()) { + result.add(AppPermissionStat( + packageName = app.packageName, + appName = getAppName(app.packageName), + accessCounts = stats, + isSystemApp = (app.flags and ApplicationInfo.FLAG_SYSTEM) != 0 + )) + } + } + return result.sortedByDescending { it.totalAccesses } + } + + // ── Network data usage (last 24 hours) ────────────────────── + fun getSleepTimeDataUsage(): List { + if (!hasUsageStatsPermission()) return emptyList() + + val networkStats = context.getSystemService(NetworkStatsManager::class.java) + + val now = System.currentTimeMillis() + val yesterday = now - 86400000L + + val result = mutableListOf() + + try { + val summary = networkStats.querySummary( + ConnectivityManager.TYPE_MOBILE, null, yesterday, now + ) + val bucket = NetworkStats.Bucket() + val appTotals = mutableMapOf() // uid → bytes sent + + while (summary.hasNextBucket()) { + summary.getNextBucket(bucket) + val uid = bucket.uid + if (uid > 1000) { // skip system UIDs + appTotals[uid] = (appTotals[uid] ?: 0) + bucket.txBytes + } + } + summary.close() + + val pm = context.packageManager + for ((uid, bytes) in appTotals) { + if (bytes < 100_000) continue // skip < 100KB + try { + val pkgs = pm.getPackagesForUid(uid) ?: continue + val pkg = pkgs.first() + val appName = getAppName(pkg) + result.add(AppDataUsage( + packageName = pkg, + appName = appName, + bytesSent = bytes, + mbSent = bytes / 1_048_576.0 + )) + } catch (e: Exception) { /* skip */ } + } + } catch (e: Exception) { + Log.e("TelemetryHelper", "Network stats error: ${e.message}") + } + + return result.sortedByDescending { it.bytesSent } + } + + // ── Story generator ───────────────────────────────────────── + fun generatePrivacyStories( + sensors: List, + permissions: List, + dataUsage: List + ): List { + val stories = mutableListOf() + + for (sensor in sensors) { + stories.add(PrivacyStory( + severity = "CRITICAL", + emoji = if (sensor.sensor == "microphone") "🎙️" else "📷", + english = "${sensor.appName} is ${sensor.sensor} RIGHT NOW", + hindi = "${sensor.appName} अभी आपका ${ + if (sensor.sensor == "microphone") "माइक" else "कैमरा" + } इस्तेमाल कर रहा है", + packageName = sensor.packageName + )) + } + + for (app in permissions.take(5)) { + val micCount = app.accessCounts["microphone"] ?: 0 + val locCount = app.accessCounts["location"] ?: 0 + val contactCount = app.accessCounts["contacts"] ?: 0 + + if (micCount > 10) { + stories.add(PrivacyStory( + severity = "HIGH", + emoji = "🎙️", + english = "${app.appName} accessed your microphone $micCount times this week", + hindi = "${app.appName} ने इस हफ्ते $micCount बार माइक एक्सेस किया", + packageName = app.packageName + )) + } + if (locCount > 20) { + stories.add(PrivacyStory( + severity = "HIGH", + emoji = "📍", + english = "${app.appName} tracked your location $locCount times this week", + hindi = "${app.appName} ने $locCount बार आपकी लोकेशन ट्रैक की", + packageName = app.packageName + )) + } + if (contactCount > 0 && !isCommunicationApp(app.packageName)) { + stories.add(PrivacyStory( + severity = "MEDIUM", + emoji = "👥", + english = "${app.appName} read your contacts — this app doesn't need them", + hindi = "${app.appName} ने आपके contacts पढ़े — इस app को इसकी जरूरत नहीं", + packageName = app.packageName + )) + } + } + + for (app in dataUsage.take(3)) { + if (app.mbSent > 50) { + stories.add(PrivacyStory( + severity = "MEDIUM", + emoji = "📤", + english = "${app.appName} sent ${app.mbSent.toInt()} MB of your data", + hindi = "${app.appName} ने आपका ${app.mbSent.toInt()} MB डेटा भेजा", + packageName = app.packageName + )) + } + } + + if (stories.isEmpty()) { + stories.add(PrivacyStory( + severity = "SAFE", + emoji = "✅", + english = "No suspicious activity detected in the last 24 hours", + hindi = "पिछले 24 घंटों में कोई संदिग्ध गतिविधि नहीं मिली", + packageName = "" + )) + } + + return stories.sortedBy { + when (it.severity) { "CRITICAL" -> 0; "HIGH" -> 1; "MEDIUM" -> 2; else -> 3 } + } + } + + fun hasUsageStatsPermission(): Boolean { + val appOps = context.getSystemService(AppOpsManager::class.java) + val mode = appOps.unsafeCheckOpNoThrow( + AppOpsManager.OPSTR_GET_USAGE_STATS, + android.os.Process.myUid(), context.packageName + ) + return mode == AppOpsManager.MODE_ALLOWED + } + + private fun getAppName(packageName: String): String { + return try { + val ai = context.packageManager.getApplicationInfo(packageName, 0) + context.packageManager.getApplicationLabel(ai).toString() + } catch (e: Exception) { packageName } + } + + private fun isCommunicationApp(pkg: String): Boolean { + return pkg.contains("whatsapp") || pkg.contains("telegram") || + pkg.contains("signal") || pkg.contains("gmail") || + pkg.contains("message") || pkg.contains("dialer") + } +} + +// Data classes +data class SensorAccess(val packageName: String, val appName: String, + val sensor: String, val isActive: Boolean) +data class AppPermissionStat(val packageName: String, val appName: String, + val accessCounts: Map, val isSystemApp: Boolean) { + val totalAccesses get() = accessCounts.values.sum() +} +data class AppDataUsage(val packageName: String, val appName: String, + val bytesSent: Long, val mbSent: Double) +data class PrivacyStory(val severity: String, val emoji: String, + val english: String, val hindi: String, val packageName: String) diff --git a/android/app/src/main/res/drawable-v21/launch_background.xml b/android/app/src/main/res/drawable-v21/launch_background.xml new file mode 100644 index 0000000000000000000000000000000000000000..f74085f3f6a2b995f8ad1f9ff7b2c46dc118a9e0 --- /dev/null +++ b/android/app/src/main/res/drawable-v21/launch_background.xml @@ -0,0 +1,12 @@ + + + + + + + + diff --git a/android/app/src/main/res/drawable/launch_background.xml b/android/app/src/main/res/drawable/launch_background.xml new file mode 100644 index 0000000000000000000000000000000000000000..304732f8842013497e14bd02f67a55f2614fb8f7 --- /dev/null +++ b/android/app/src/main/res/drawable/launch_background.xml @@ -0,0 +1,12 @@ + + + + + + + + diff --git a/android/app/src/main/res/layout/widget_4x2.xml b/android/app/src/main/res/layout/widget_4x2.xml new file mode 100644 index 0000000000000000000000000000000000000000..046407d44b6c76244e77dbc883e81c4852dbd0b1 --- /dev/null +++ b/android/app/src/main/res/layout/widget_4x2.xml @@ -0,0 +1,85 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/android/app/src/main/res/layout/widget_layout.xml b/android/app/src/main/res/layout/widget_layout.xml new file mode 100644 index 0000000000000000000000000000000000000000..bd9f013900d80483e544f4def7b5006c5d2a0031 --- /dev/null +++ b/android/app/src/main/res/layout/widget_layout.xml @@ -0,0 +1,52 @@ + + + + + + + + + + + + + + + + + + + + + + + diff --git a/android/app/src/main/res/values-night/styles.xml b/android/app/src/main/res/values-night/styles.xml new file mode 100644 index 0000000000000000000000000000000000000000..06952be745f9fa6fa75196e830d9578eb2ee631d --- /dev/null +++ b/android/app/src/main/res/values-night/styles.xml @@ -0,0 +1,18 @@ + + + + + + + diff --git a/android/app/src/main/res/values/colors.xml b/android/app/src/main/res/values/colors.xml new file mode 100644 index 0000000000000000000000000000000000000000..0c5f75bf09cef497af3971ad8e4b9501537ca3a0 --- /dev/null +++ b/android/app/src/main/res/values/colors.xml @@ -0,0 +1,7 @@ + + + #FFCC2222 + #FFCC7700 + #FF227722 + #FF333355 + diff --git a/android/app/src/main/res/values/strings.xml b/android/app/src/main/res/values/strings.xml new file mode 100644 index 0000000000000000000000000000000000000000..b36ec702a68c2468df7022e113ca6154c09d5fea --- /dev/null +++ b/android/app/src/main/res/values/strings.xml @@ -0,0 +1,8 @@ + + + Premithius + Premithius Shield + Premithius uses Accessibility to detect scam apps opening and protect your privacy. No data leaves your device. + App protection and scam detection + Premithius live security summary + diff --git a/android/app/src/main/res/values/styles.xml b/android/app/src/main/res/values/styles.xml new file mode 100644 index 0000000000000000000000000000000000000000..cb1ef88056edd1caf99a935e434e7ff6943a0ef6 --- /dev/null +++ b/android/app/src/main/res/values/styles.xml @@ -0,0 +1,18 @@ + + + + + + + diff --git a/android/app/src/main/res/xml/accessibility_service_config.xml b/android/app/src/main/res/xml/accessibility_service_config.xml new file mode 100644 index 0000000000000000000000000000000000000000..0d93722581febd9940799f16d678f1a9be667380 --- /dev/null +++ b/android/app/src/main/res/xml/accessibility_service_config.xml @@ -0,0 +1,11 @@ + + diff --git a/android/app/src/main/res/xml/method.xml b/android/app/src/main/res/xml/method.xml new file mode 100644 index 0000000000000000000000000000000000000000..4678c748628f7508d1ce56c43ae84bb37f5db9bc --- /dev/null +++ b/android/app/src/main/res/xml/method.xml @@ -0,0 +1,7 @@ + + + + diff --git a/android/app/src/main/res/xml/premithius_widget_info.xml b/android/app/src/main/res/xml/premithius_widget_info.xml new file mode 100644 index 0000000000000000000000000000000000000000..3f54f9c384aae04cf5c699a9705e046597d7f27a --- /dev/null +++ b/android/app/src/main/res/xml/premithius_widget_info.xml @@ -0,0 +1,12 @@ + + + diff --git a/android/app/src/profile/AndroidManifest.xml b/android/app/src/profile/AndroidManifest.xml new file mode 100644 index 0000000000000000000000000000000000000000..399f6981d5d35475eb18e6068ae67cdd7c731978 --- /dev/null +++ b/android/app/src/profile/AndroidManifest.xml @@ -0,0 +1,7 @@ + + + + diff --git a/android/build.gradle.kts b/android/build.gradle.kts new file mode 100644 index 0000000000000000000000000000000000000000..d08ad63942d7b2dc4025216531d9fc89c3915ec2 --- /dev/null +++ b/android/build.gradle.kts @@ -0,0 +1,25 @@ +allprojects { + repositories { + google() + mavenCentral() + maven { url = uri("https://jitpack.io") } + } +} + +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/android/build/reports/problems/problems-report.html b/android/build/reports/problems/problems-report.html new file mode 100644 index 0000000000000000000000000000000000000000..4622f69bbbe3226d926038792a1669bc5407bd98 --- /dev/null +++ b/android/build/reports/problems/problems-report.html @@ -0,0 +1,663 @@ + + + + + + + + + + + + + Gradle Configuration Cache + + + +
+ +
+ Loading... +
+ + + + + + diff --git a/android/gradle.properties b/android/gradle.properties new file mode 100644 index 0000000000000000000000000000000000000000..fbee1d8cdafcdef3dfd5e228d9cc1688165504a0 --- /dev/null +++ b/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/android/gradle/wrapper/gradle-wrapper.properties b/android/gradle/wrapper/gradle-wrapper.properties new file mode 100644 index 0000000000000000000000000000000000000000..e4ef43fb98df49e4a065ae4c2777f54463bf65b7 --- /dev/null +++ b/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/android/settings.gradle.kts b/android/settings.gradle.kts new file mode 100644 index 0000000000000000000000000000000000000000..ca7fe065c167b304c620950482ab6349d0ab124a --- /dev/null +++ b/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/assets/blocklist/india_scam_domains.txt b/assets/blocklist/india_scam_domains.txt new file mode 100644 index 0000000000000000000000000000000000000000..94240ddca82fafa8d5a3666169b9146253718974 --- /dev/null +++ b/assets/blocklist/india_scam_domains.txt @@ -0,0 +1,68 @@ +# KYC Fraud domains +hdfcbank-kyc.net +sbi-kyc-verify.top +icici-kyc-update.xyz +axis-kyc-expire.click +pnb-kyc-alert.com +bob-kyc-update.in + +# Fake bank portals +netbanking-hdfc.com +sbi-netbanking.xyz +icici-ibank.top +hdfc-secure-login.net +axisbank-online-secure.com +sbi-reward-points.online +hdfc-reward-redeem.in +icici-card-block.xyz + +# UPI Fraud domains +upi-reward-claim.xyz +paytm-cashback-offer.top +phonepe-winner.click +gpay-prize.tk +bhim-upi-cashback.in +upi-refund-process.top +phonepe-support-care.com + +# Lottery / Prize scams +india-lottery-winner.net +bsnl-prize-claim.xyz +jio-recharge-free.top +airtel-winner-prize.click +kbc-lottery-winner.in +tata-safari-winner.club +mahindra-thar-prize.com + +# Fake government portals +pm-kisan-apply.xyz +aadhar-update-now.top +pan-verify-online.click +income-tax-refund.net +epfo-claim-status.in +passport-sewa-india.org +voter-id-verify.online +cowin-certificate-download.click + +# Investment scams +trading-profit-india.xyz +stock-tip-guaranteed.top +crypto-india-profit.click +bitcoin-doubler.in +nse-bse-tips.club +zerodha-trading-bonus.online + +# Loan app harassment +insta-loan-now.xyz +quick-cash-app.top +easy-money-india.click +dhani-loan-approve.in +kreditbee-instant.site +navi-loan-offer.xyz + +# Extortion / Threats +cyber-crime-notice.in +cbi-investigation-portal.org +rbi-penalty-payment.com +customs-clearance-fee.xyz +trai-number-block.top diff --git a/assets/seed_embeddings.json b/assets/seed_embeddings.json new file mode 100644 index 0000000000000000000000000000000000000000..d9cc423e0fe2b2efa1fd465406e3a0200bfa28f9 --- /dev/null +++ b/assets/seed_embeddings.json @@ -0,0 +1 @@ +[{"embedding":[-0.01051,-0.15941,-0.011092,-0.053174,0.025861,0.024439,-0.000328,-0.08898,-0.005509,0.032369,0.051486,-0.033268,-0.03129,-0.069531,0.014992,-0.017737,0.015214,-0.039067,-0.030631,0.005001,-0.02306,-0.044235,-0.019992,0.014919,-0.027993,-0.020078,-0.008308,0.081545,-0.025772,-0.015433,-0.016781,-0.026985,0.010299,-0.024397,0.116517,-0.074533,-0.067267,0.050521,-0.005599,-0.120109,0.040577,-0.107096,-0.041978,0.015341,0.084489,0.064796,-0.02273,0.014983,0.052403,-0.012166,0.030837,-0.01361,-0.047714,-0.001119,-0.002112,0.082118,0.052922,0.10518,0.156412,0.012637,-0.067609,0.058224,0.010755,0.033273,-0.002364,-0.018899,-0.078033,-0.008535,0.038914,0.016252,-0.065858,-0.029815,-0.046126,-0.002277,0.022413,0.028142,-0.027774,-0.031787,0.067866,-0.061299,-0.020458,-0.037387,0.078259,-0.02865,-0.024447,-0.002912,0.03492,-0.039963,-0.024835,-0.034733,0.14106,0.024037,0.132199,-0.022462,-0.0109,-0.021948,0.009746,0.035113,-0.070509,-0.024131,0.085218,0.054125,-0.077848,-0.002054,0.04243,-0.043318,0.018616,0.02359,0.063101,-0.021717,-0.006554,0.027016,0.025998,-0.063837,-0.051636,-0.021013,0.002598,-0.056756,-0.032921,-0.024223,0.016975,-0.063033,0.023843,-0.093106,-0.013447,-0.066976,0.03875,0.0,0.013134,0.036785,-0.012681,-0.071344,-0.00885,-0.074785,0.062555,-0.00239,-0.005278,0.038626,-0.028275,-0.05231,-0.010358,-0.054744,-0.100678,-0.007101,0.005,0.04996,0.020473,0.167695,-0.028977,-0.054981,0.097173,-0.100414,-0.023356,0.03969,0.010635,-0.018015,0.136293,0.03656,-0.041138,-0.060513,-0.003707,0.018813,-0.064182,-0.00392,0.031539,-0.08817,-0.032408,-0.016311,-0.037197,-0.02535,-0.031478,-0.007132,0.022648,0.034253,0.041528,0.038238,-0.062801,0.07258,-0.054596,-0.073505,-0.055648,-0.026936,0.009751,0.030889,0.011961,-0.041752,0.032967,0.007395,0.100373,-0.020027,-0.058763,0.032858,0.013813,-0.012478,0.020457,-0.079318,-0.039852,-0.029114,0.022424,0.018343,0.03234,0.030646,-0.09515,0.010745,-0.079121,0.056879,-0.06825,0.028678,0.043341,0.013957,-0.030407,0.005929,0.015066,0.10668,-0.04251,0.064172,-0.050215,-0.005757,-0.036153,-0.05678,0.113718,0.067937,-0.007345,-0.0,-0.045619,-0.027122,-0.059018,-0.018434,0.021883,-0.005632,0.011592,0.099076,0.042631,0.053071,0.122039,0.00476,0.003059,-0.069898,-0.024901,-0.015548,-0.016622,0.022808,-0.116665,0.065832,-0.028222,-0.024653,-0.007084,0.13163,-0.065342,0.057786,0.016812,0.088877,0.01801,0.018293,0.038874,-0.032588,-0.131004,0.054418,0.015865,-0.085046,0.051202,0.014885,-0.010774,-0.008049,0.04223,0.020425,-0.033103,-0.035423,0.020394,-0.024237,0.058226,-0.002227,0.029305,0.032481,-0.0003,-0.073244,0.086377,0.061333,-0.073314,0.075944,0.139255,-0.003676,0.057173,-0.031788,-0.035217,0.032798,-0.014393,0.06199,0.11449,0.094105,0.049156,0.033568,0.06453,-0.047174,-0.01386,-0.079446,0.073633,0.043516,0.046052,-0.030098,-0.006206,0.065273,0.047665,0.042497,0.067925,-0.005436,-0.041129,-0.009499,0.051421,-0.081321,0.044367,-0.033746,0.032994,-0.107606,-0.024271,-0.08308,-0.106424,0.061783,-0.004281,-0.0,0.020461,-0.047728,0.004476,0.00368,0.012829,-0.024816,-0.008464,-0.041432,-0.03513,-0.050358,0.052869,0.053704,-0.009069,-0.013894,0.032506,-0.015459,-0.011058,0.009022,0.021287,-0.062896,0.005801,-0.036387,0.063751,0.003516,0.004682,-0.015285,0.046881,0.012288,0.010377,-0.050788,-0.05035,0.009165,0.016449,0.034505,0.012743,0.065065,0.006332,-0.017903,0.008969,0.086672,-0.037051,-0.014256,0.057337,-0.055545,0.008208,0.027105,-0.039563,0.062763,0.074763,-0.020842,-0.040047,-0.001294,0.039948,-0.063745,-0.006392,-0.042079,0.023305,-0.030676,-0.034171,0.040792,0.081423,-0.018415,-0.027489,0.003373],"category":"KYC Fraud","source":"seed_minilm"},{"embedding":[-0.020986,-0.103746,-0.005031,0.002111,0.092685,-0.016234,0.064117,-0.091895,0.037338,-0.027209,0.05248,0.043106,0.000553,-0.009529,0.00728,0.017688,-0.070147,-0.03034,-0.047833,-0.020356,0.001012,0.002482,-0.026363,0.081948,-0.029211,-0.04716,0.014404,0.060485,-0.056948,-0.040891,0.022064,0.062456,0.010178,-0.102786,0.030819,-0.027791,0.026567,-0.00084,0.046173,-0.079047,-0.002091,-0.091418,-0.00641,-0.036575,0.099599,0.000267,-0.056083,0.014087,0.041796,0.038649,0.008432,-0.039846,0.02683,-0.008088,-0.03983,0.039515,0.081035,0.003922,0.067873,-0.013062,-0.019282,0.024917,0.041374,0.03404,-0.093962,0.086132,-0.033222,-0.104455,0.0126,-0.026427,0.053195,-0.013943,-0.078228,0.012505,-0.02029,0.022604,0.072016,0.01038,0.053867,0.061944,0.007442,-0.069519,-0.028655,0.019094,-0.055798,0.03622,9.4e-05,-0.027438,-0.064608,0.053278,0.117645,0.019891,0.067394,-0.061911,-0.038379,-0.035535,-0.023172,-0.046895,-0.046106,0.064303,-0.008417,0.02982,-0.030498,0.027891,0.051228,0.050795,0.065629,-0.02023,-0.000248,-0.02364,0.036693,-0.03895,0.039546,0.074149,-0.03496,0.085078,-0.031822,0.081371,0.035347,-0.052623,0.072262,0.096354,0.014984,-0.054493,-0.062174,-0.045465,0.076606,-0.0,0.067609,0.057725,-0.028558,0.027489,0.017897,-0.066385,-0.026661,0.026068,-0.058585,-0.001106,1.9e-05,-0.039477,0.035549,-0.0127,-0.002729,-0.04713,0.090673,0.024347,0.076848,0.035661,0.063699,-0.082026,0.045831,0.020361,-0.044843,0.067771,0.094615,0.041169,0.040722,0.012828,-0.011431,0.028994,0.013061,0.022246,-0.004899,-0.005957,0.028769,-0.044632,-0.098432,-0.024199,0.06088,0.000249,-0.078786,0.017984,-0.016168,-0.02873,-0.018263,0.013353,0.0203,0.029357,-0.096179,0.041788,-0.036264,-0.017041,0.004333,0.030355,0.015835,0.020552,0.029657,-0.019223,0.098558,-0.00472,-0.034758,-0.016265,-0.046898,0.031611,-0.018768,-0.026294,-0.029713,0.040807,-0.00399,-0.03142,0.041685,0.072296,-0.080737,-0.019847,-0.090483,0.048939,-0.009744,0.000713,0.037739,-0.03888,-0.014574,0.02585,0.017241,0.082504,0.026739,0.050766,-0.039549,0.000601,-0.083427,0.053611,0.049311,0.072423,-0.025447,0.0,-0.075126,0.007713,-0.056282,0.0052,-0.03845,-0.047697,-0.03354,0.0622,-0.014466,0.041157,-0.01148,0.006541,-0.035169,-0.059911,0.041628,-0.044069,0.019506,-0.012195,-0.131594,0.040015,-0.03571,0.046353,0.079035,-0.009813,-0.039017,-0.005878,0.055417,0.063394,-0.064292,0.049255,0.064872,-0.068278,-0.09298,0.050543,0.01324,-0.074067,0.012116,-0.027315,0.065934,-0.025047,0.024301,0.060099,-0.018928,0.007848,0.006353,-0.028167,0.02826,-0.120082,-0.012804,-0.002794,-0.088464,-0.065894,0.104343,0.012112,0.018642,0.006792,0.088442,0.030509,0.027636,-0.038643,-0.017035,0.007654,-0.040737,0.094903,0.103051,0.017659,0.065742,-0.05673,0.135259,-0.055929,0.010606,-0.006046,0.054056,0.113057,0.008208,-0.085998,-0.110016,0.014792,-0.01652,-0.019546,0.052214,-0.020812,-0.102015,0.011536,-0.01718,-0.110238,0.032403,0.015898,0.085357,-0.044215,0.022756,-0.034865,-0.13018,0.004824,-0.020284,-0.0,0.03937,-0.020034,0.027185,0.129767,0.09899,-0.00592,-0.050226,-0.109199,-0.062866,-0.063358,-0.068156,0.018229,-0.033685,-0.011031,0.024688,-0.059232,-0.061469,0.023359,0.013921,-0.037215,0.027871,0.013928,0.00373,-0.013531,-0.051249,-0.035071,0.015319,0.037263,-0.00682,-0.071382,-0.053823,-0.006284,-0.000859,-0.111257,-0.049192,0.099308,0.002713,-0.032812,0.054666,0.028295,-0.041192,-0.003075,0.034503,-0.061497,0.013735,0.022179,-0.075809,0.057472,0.062651,0.000886,-0.00972,-0.058349,0.046563,0.101785,-0.058035,-0.013223,0.003244,-0.047798,-0.027286,-0.037602,0.102694,-0.075251,-0.040007,-0.110069],"category":"KYC Fraud","source":"seed_minilm"},{"embedding":[-0.043341,-0.090877,-0.038174,-0.069542,0.033256,-0.039983,-0.016025,-0.079223,0.047099,0.099348,0.070973,0.032147,0.015534,0.031478,0.001218,0.012606,-0.02309,-0.084086,-0.026434,0.019558,-0.076628,-0.022547,-0.003959,-0.003814,0.01203,-0.01287,-0.012378,0.119423,-0.041573,0.0038,0.019036,0.050693,-0.077121,-0.070618,0.08776,-0.013382,0.019537,0.047208,0.004436,-0.064772,-0.017152,-0.053915,0.028406,-0.022296,0.056251,0.127664,-0.002443,-0.066146,0.03898,0.072598,0.010738,-0.050227,-0.059209,-0.030513,-0.054411,0.038283,0.019639,0.117877,0.10369,-0.042969,-0.060932,0.036832,-0.015596,0.044132,-0.017431,0.016126,-0.125544,0.028623,-0.028148,0.056589,0.024583,-0.099477,-0.062768,-0.031181,-0.010065,0.077275,0.048264,-0.052801,0.102335,-0.067883,-0.029252,-0.043224,0.008133,0.037676,-0.021293,0.033229,-0.020574,0.008289,0.001691,0.003269,0.094724,0.047159,0.080199,0.008491,0.068059,-0.086977,0.012471,0.081989,-0.073209,0.002076,0.061653,0.071072,-0.020259,0.059458,0.030515,-0.063354,0.084803,0.028089,0.024951,0.005101,-0.040431,0.051587,0.005448,-0.002094,0.011888,0.039044,-0.032392,-0.036135,-0.027373,0.003162,0.03531,0.066934,-0.008628,-0.029014,-0.050498,0.008157,0.062508,-0.0,-0.077168,0.015323,-0.004531,-0.074563,-0.051939,-0.04423,-0.079498,-0.045784,-0.032464,0.111008,-0.055073,0.000639,0.033991,-0.031642,-0.055891,-0.001489,0.086458,0.091605,0.014183,0.114228,0.04989,-0.112048,0.067592,-0.05317,-0.074318,0.05506,0.031723,0.027184,0.110763,0.004645,0.001979,-0.048552,0.005353,-0.005551,-0.04672,-0.001531,0.037758,-0.090773,-0.064258,0.032071,-0.012417,-0.070663,-0.036254,0.016554,-0.001476,0.057155,0.015875,-0.00594,0.010973,0.100792,-0.080986,-0.010999,-0.137124,-0.008845,-0.000431,-0.023647,0.008583,0.024249,-0.029749,-0.082065,0.077112,-0.032856,-0.092878,-0.008524,0.010075,-0.036927,-0.018431,-0.047029,-0.095978,0.011697,-0.05215,0.006618,0.066983,0.07141,0.001819,-0.060788,-0.061808,0.071202,-0.045103,0.010998,-0.023877,-0.013419,-0.10038,-0.0208,0.022397,0.071169,-0.019818,0.014802,0.008062,-0.043001,-0.054684,-0.066434,0.050019,0.070475,-0.04848,-0.0,-0.065723,0.026426,-0.000493,0.007088,0.031154,0.029813,0.050305,0.083885,0.024605,0.031491,0.050891,-0.034271,0.023406,-0.05597,-0.019096,-0.041906,-0.043585,0.073854,-0.002506,0.0235,0.01526,-0.011129,0.034423,0.090143,-0.040466,0.106464,0.006796,0.010037,0.033938,0.040995,-0.026426,-0.001107,-0.077272,0.012107,0.02186,-0.007895,-0.000688,-0.0191,-0.047948,-0.051209,0.017181,0.034059,-0.040638,0.013304,0.005465,-0.03543,0.04677,0.053355,0.039261,0.01687,-0.056519,0.004247,0.139148,-0.019327,-0.011392,0.054848,0.117208,-0.027462,0.051305,-0.0562,-0.012374,-0.027096,-0.026499,0.01979,0.098172,0.063023,0.095277,0.057846,0.075472,0.046409,-0.048501,-0.054456,0.07869,-0.019721,0.041216,-0.061468,-0.080604,-0.010929,-0.003669,0.0009,0.063243,0.015972,-0.008765,0.030567,0.044341,-0.03269,-0.024804,0.025092,0.041832,-0.088672,-0.015385,-0.118509,-0.026948,0.096927,0.001069,-0.0,0.001483,-0.040826,0.017852,0.012155,0.052596,0.032882,-0.038555,-0.036115,-0.030554,0.014535,-0.020005,0.035804,-0.077616,-0.020234,-0.032697,-0.024218,-0.042532,-0.008557,0.05161,-0.058046,0.000545,-0.017646,0.02618,-0.052754,-0.043398,0.021068,0.011885,0.120062,0.004306,-0.066071,-0.091774,0.0161,0.034499,-0.072809,-0.093743,0.013338,0.023808,0.059803,-0.008386,0.040829,-0.069274,0.002775,0.046702,-0.03858,-0.030286,0.07155,-0.02463,0.024181,0.015102,-0.066743,-0.059115,-0.043911,0.059045,0.019516,-0.041133,0.028847,-0.050032,-0.028641,-0.010814,0.005139,0.01545,-0.020172,-0.048283,-0.098819],"category":"KYC Fraud","source":"seed_minilm"},{"embedding":[0.042958,-0.012447,-0.063102,-0.016295,0.045217,-0.030786,0.118973,-0.009404,0.061282,-0.052293,0.030929,0.016418,0.019332,0.040446,-0.070709,-0.04779,-0.005917,-0.055259,-0.049222,-0.015272,-0.00265,-0.022257,-0.05004,0.002009,-0.028768,-0.049602,-0.003036,0.020259,-0.081489,0.001567,-0.006479,0.012876,0.01082,-0.049164,0.059945,-0.111258,-0.054735,0.103469,0.134497,-0.090374,0.014838,-0.081507,0.014243,-0.05182,0.058198,0.072379,-0.034039,-0.008325,-0.029237,0.094637,0.042981,-0.034173,0.010989,-0.017617,0.013681,0.006904,-0.003922,-0.024097,0.017658,-0.034321,-0.002838,0.018585,0.036447,0.045534,-0.101579,0.068378,-0.05046,-0.043047,0.004575,-0.005451,0.018695,-0.072969,-0.011939,-0.013759,0.07148,0.068064,0.12009,-0.00089,0.08298,-0.033093,-0.02079,-0.047505,0.083705,-0.03954,-0.028774,0.04677,0.027186,0.031287,0.012574,-0.026261,0.068786,0.107896,0.050728,0.011517,-0.03577,-0.121979,-0.051386,-0.032111,-0.098851,0.038412,0.058227,0.032334,-0.004814,0.09988,-0.017502,-0.071017,0.067302,0.037409,0.020209,-0.03381,-0.060693,0.051574,0.082848,-0.043936,-0.046029,0.056629,-0.015153,0.071336,0.040843,0.04396,-0.014794,0.025166,-0.009526,-0.078864,0.00336,-0.007348,0.037482,0.0,-0.052568,0.087327,-0.018005,-0.119047,0.065069,-0.072588,0.013548,-0.021377,-0.038096,-0.01422,-0.065396,-0.054796,-0.017305,-0.018136,-0.057594,0.057381,0.099041,0.013307,0.068291,0.035343,0.033781,-0.073134,0.046976,0.036293,0.075431,0.017606,0.038938,0.02816,0.09139,0.009486,-0.049491,-0.058054,-0.065968,-0.002993,0.036691,0.020741,-0.059485,-0.003667,0.003518,0.033093,-0.040326,0.00033,-0.034695,-0.052808,-0.006668,0.103254,-0.020863,0.07709,0.01888,-0.045376,-0.014674,0.027597,-0.05803,-7.5e-05,-0.026675,-0.018636,-0.05074,-0.034579,-0.002195,-0.071084,0.0441,-0.099901,-0.095707,-0.061352,-0.028033,0.041682,-0.059535,-0.017893,-0.03764,-0.055934,-0.084178,-0.005155,0.088378,0.070562,-0.102489,0.021747,-0.059614,0.029264,0.058496,0.040807,-0.003618,0.063414,0.034852,-0.024189,0.067677,-0.005754,-0.015223,-0.009485,-0.069061,0.01281,0.013628,0.019243,-0.019452,0.0679,-0.043681,-0.0,-0.029362,-0.022597,-0.125834,-0.007696,-0.087418,-0.001573,-0.007377,0.047796,0.000417,-0.001309,0.109972,0.032448,0.008171,0.010649,-0.034859,-0.032851,-0.001078,0.070495,-0.021417,0.038739,0.01621,0.002919,-0.069836,-0.036894,-0.136081,0.073427,-0.053382,0.057186,0.035996,-0.010621,-0.047983,0.021293,-0.005379,0.028147,0.002623,0.030965,0.058524,-0.029821,-0.059248,0.048171,0.00921,0.070909,-0.046079,0.059535,0.013775,0.062985,0.127216,-0.017731,-0.034293,0.051589,-0.008279,-0.033809,0.060307,0.002082,-0.011488,0.064266,0.161704,-0.085259,0.020343,-0.057871,-0.001173,-0.001694,-0.036265,0.04753,0.066462,0.013073,0.007913,0.053586,0.110498,-0.083358,-0.003743,-0.040092,-0.075799,-0.035748,-0.032976,0.02276,-0.024013,0.028743,-0.033585,-0.02621,0.056991,-0.01696,-0.02105,0.003244,0.017515,-0.077948,0.079714,0.004118,0.022896,-0.032328,-0.062474,0.007697,9.9e-05,0.085589,-0.034488,-0.0,0.000694,-0.035915,0.000193,-0.024163,0.086544,0.002166,0.000798,-0.030386,-0.050898,-0.04557,-0.051398,0.020308,-0.068774,-0.0485,0.025452,0.025729,-0.019442,-0.061343,0.008659,-0.02423,-0.039321,0.015002,-0.04609,-0.03188,0.034755,-0.083303,0.036128,0.013308,-0.033887,-0.032092,-0.105979,0.010939,0.105343,-0.060166,-0.001161,0.110004,0.004385,-0.015358,0.059743,-0.013307,-0.059167,-0.024854,-0.049153,-0.022543,0.073712,0.001307,-0.045375,0.003669,0.028133,-0.083339,-0.06665,0.026541,0.076886,0.04333,0.020545,0.000788,-0.031871,-0.038644,0.02564,0.063911,0.065867,-0.037644,-0.005948,-0.080407],"category":"KYC Fraud","source":"seed_minilm"},{"embedding":[-0.009836,-0.051005,-0.071249,0.014982,0.031598,-0.00385,0.043313,-0.036007,0.030022,0.064256,0.038935,0.013599,-0.032916,0.021756,-0.012584,0.066321,-0.055511,-0.06775,0.021588,-0.008704,-0.08573,0.028807,-0.01182,-0.004583,-0.012461,-0.054195,0.026746,0.095322,0.005559,-0.015202,0.024899,0.004545,-0.044603,-0.048998,0.012258,0.038138,-0.090735,0.030258,0.04702,-0.078423,0.082031,-0.039022,-0.034132,0.041809,0.087152,0.080623,-0.023493,0.020542,-0.013644,0.002405,0.077469,-0.006258,-0.051028,0.030117,-0.048685,-0.031308,-0.003695,0.074275,0.066133,-0.061546,-0.025018,0.11425,-0.031461,-0.021041,0.004015,0.042378,-0.060657,-0.01089,0.003059,0.026011,0.003823,-0.000907,-0.066881,0.020596,-0.071155,0.023033,0.065576,-0.008436,0.002818,0.042631,0.005621,-0.070464,-0.061091,0.004964,-0.00681,0.049256,-0.024526,-0.001076,-0.098706,0.00125,0.172586,0.076831,0.099686,0.005578,-0.021415,-0.070792,-0.023736,0.048395,-0.034843,0.022373,0.013654,0.116856,-0.105915,0.021302,-0.005183,0.005385,0.099506,-0.015163,0.042807,0.00594,-0.100683,0.047837,-0.007956,-0.012638,-0.020601,0.062628,-0.082302,0.033021,-0.013955,-0.03893,-0.044716,0.070479,-0.030875,-0.017222,-0.058492,-0.029354,0.044875,0.0,-0.074087,-0.009124,0.008839,-0.014072,0.017216,-0.023287,0.02729,-0.03767,-0.050534,0.034556,-0.002787,-0.082505,0.041919,-0.078247,-0.084504,-0.015236,0.076098,0.020606,0.059444,0.097522,0.027861,-0.051404,0.028655,0.044324,0.008377,0.026073,0.047771,0.024317,0.032871,-0.006884,-0.037483,0.088905,-0.051326,0.01203,-0.049471,-0.076173,0.061089,-0.050469,-0.083941,-0.045822,0.008923,-0.07142,-0.016106,0.002034,-0.005006,0.030099,-0.02523,0.122112,-0.035273,0.067035,-0.031561,0.029348,-0.072767,0.031255,-0.04325,-0.010441,-0.050806,-0.001999,0.00624,-0.006922,0.120564,-0.047325,-0.054709,-0.07394,-0.056427,-0.029105,0.02417,-0.009785,-0.049323,0.036654,0.03698,-0.019332,0.085164,0.063879,-0.103256,-0.008549,-0.093093,-0.002514,-0.044429,0.0456,0.020612,-0.015207,0.027297,-0.016598,0.039012,0.071041,-0.00086,-0.032547,-0.027397,0.033447,-0.040979,0.025062,0.060855,0.045677,-0.001453,-0.0,-0.052945,0.011192,-0.137901,-0.044002,0.054648,-0.010004,0.016942,0.057863,-0.035558,0.052449,0.067649,0.026497,-0.060245,-0.044717,0.010139,-0.016313,-0.018842,0.107633,-0.030214,0.019051,-0.014219,0.056944,0.037721,0.005816,-0.024233,0.063953,0.046211,0.108216,-0.013655,0.036567,0.023316,-0.017212,-0.084731,0.087224,-0.02369,-0.050999,0.046596,-0.076723,0.021984,-0.019858,-0.012031,0.091078,-0.071067,-0.007787,0.052503,0.030303,0.020543,-0.03279,0.049874,-0.013026,0.001857,-0.002067,0.123906,0.051205,0.040578,0.047537,0.050013,-0.026558,0.101129,-0.018643,-0.028436,-0.017312,-0.032505,0.048199,0.103736,-0.028256,0.140065,0.020069,0.112115,-0.015203,-0.045053,-0.033054,-0.013211,0.071711,-0.008087,0.019855,-0.044165,0.060652,-0.01561,-0.015096,0.021059,0.011126,-0.038628,-0.00935,-0.039001,-0.044267,0.038558,0.01833,0.05751,-0.04447,0.015016,-0.091559,-0.038349,0.095252,-0.005372,-0.0,-0.001483,-0.066105,-0.022681,0.039699,0.1014,0.009606,-0.027512,-0.083979,-0.093235,-0.035136,-0.080617,-0.05709,-0.004149,0.016368,0.038333,-0.07786,-0.008634,0.004554,0.016372,-0.100862,-0.02127,0.02063,-0.029286,-0.019035,-0.062187,-0.014336,0.020899,0.055077,-0.006852,-0.013079,-0.060941,0.016666,0.064424,-0.120408,-0.055049,0.096979,0.023667,-0.028999,0.002644,0.001821,-0.060701,-0.046662,0.074118,-0.008561,0.020064,0.015271,-0.044282,0.037403,0.050846,-0.024912,0.030778,-0.003856,0.042485,-0.024272,-0.04422,-0.052277,-0.100619,-0.001482,-0.036161,-0.099666,0.056487,-0.044013,-0.119714,-0.047383],"category":"KYC Fraud","source":"seed_minilm"},{"embedding":[-0.011263,-0.098861,0.013444,-0.046014,-0.020559,0.005807,-0.014705,-0.049122,0.007665,0.026536,0.059307,-0.053248,-0.109261,-0.055559,0.006309,-0.043596,0.048424,-0.064002,0.008638,0.045162,-0.007005,-0.018031,-0.059358,0.002341,0.002158,0.001096,0.018539,0.086118,-0.015578,-0.036087,0.002775,0.051971,0.053998,-0.008348,0.118492,-0.040484,-0.071912,0.027538,0.011162,-0.098211,0.021522,-0.033859,-0.035321,-0.027044,0.110529,0.038683,-0.022244,0.024794,0.089004,-0.025785,0.02627,0.030679,-0.062784,-0.014267,0.007217,0.042376,0.070702,0.069809,0.114115,0.002925,-0.015504,0.052483,-0.003039,0.001259,-0.07328,0.000203,-0.069367,-0.014467,0.00125,0.026871,-0.02794,0.0041,-0.002611,-0.014489,0.002959,0.057414,-0.017015,-0.047924,0.051769,-0.064792,-0.067055,-0.048878,0.112875,-0.027034,-0.001654,-0.021065,-0.003027,-0.066267,-0.024265,-0.08741,0.072655,0.068261,0.084613,-0.031452,-0.000503,-0.013666,0.03645,0.010701,-0.089702,-0.008472,0.082289,0.11135,-0.072146,0.02723,0.035516,-0.061877,0.036375,0.0132,0.063451,-0.052964,-0.034404,0.006701,-0.006356,-0.070661,-0.046874,-0.042018,-0.004056,-0.053857,0.009388,-0.054175,-0.004859,-0.039811,-0.00319,-0.05747,-0.045262,-0.05925,0.062063,0.0,0.036935,0.008219,-0.000281,-0.043375,-0.014917,-0.087649,0.029857,-0.026668,0.007542,0.036497,-0.057792,-0.04883,0.0159,-0.027193,-0.093278,-0.016884,-0.017055,0.033496,0.028513,0.161725,-0.006254,-0.098059,0.0833,-0.108867,-0.030028,0.081027,0.026106,-0.021924,0.148128,0.047596,0.011658,-0.075973,0.0269,0.009015,-0.059093,0.029337,0.025425,-0.042347,-0.024089,-0.030226,-0.037261,-0.054573,-0.027539,-0.055031,0.025585,0.022621,0.038784,0.017603,-0.068797,0.094729,-0.060514,-0.058335,-0.037676,-0.0142,0.019067,-0.01562,0.019355,0.025109,0.005243,0.000731,0.080497,-0.00432,-0.05274,0.010993,0.039167,-0.009407,-0.033562,-0.057545,-0.044804,-0.036768,-0.007196,0.027722,0.061445,0.017577,-0.089983,0.0396,-0.086986,0.03922,-0.089363,0.028715,0.037771,0.001671,-0.028453,-0.043173,0.020053,0.119977,-0.022239,0.043878,-0.00479,0.037882,-0.08278,-0.032635,0.099998,0.053641,0.01648,-0.0,-0.025523,-0.014267,-0.058593,-0.028484,-0.016168,-0.001459,0.00429,0.096854,0.065911,0.0378,0.122231,0.01924,0.005055,-0.057267,-0.032841,-0.029292,-0.013436,0.018707,-0.06322,0.029099,-0.001437,0.011038,-0.003164,0.118723,-0.071369,0.076745,0.045685,0.080794,0.044286,-0.023124,0.033503,-0.027617,-0.107707,0.091483,0.032207,-0.054455,0.030962,0.053606,-0.002435,-0.04943,0.003045,0.024574,-0.019469,0.004932,0.029047,-0.079046,0.072051,-0.045786,0.015948,0.010735,0.016207,-0.078663,0.050864,0.064503,-0.072836,0.079251,0.143073,0.000875,0.059968,-0.029731,-0.010986,0.032998,0.017275,0.032535,0.104649,0.091525,0.038056,0.041116,0.081646,-0.060325,-0.02091,-0.000164,0.040029,0.077359,0.068434,-0.006397,-0.046471,0.061974,0.043146,0.048691,0.081734,-0.051107,-0.02514,0.000136,0.042202,-0.052794,0.039708,-0.00764,-0.011571,-0.155683,-0.049446,-0.07245,-0.098803,0.063917,-0.040262,-0.0,0.006255,-0.03979,0.006985,-0.014895,0.029008,-0.046968,-0.011505,-0.05928,-0.046019,-0.088912,0.051258,0.063741,-0.031535,0.006746,0.044163,-0.034299,-0.022868,0.000142,0.036147,-0.045736,0.057599,-0.06596,0.067158,-0.007663,0.019496,-0.030472,0.033002,0.001038,0.053037,-0.072263,-0.027141,0.01432,-0.008092,0.015358,0.059543,0.008813,-0.000973,0.003232,0.033887,0.070548,-0.02195,-0.043561,0.027868,-0.074854,0.013571,0.031938,-0.005441,0.051787,0.070318,0.03193,-0.051444,-0.027601,0.056772,-0.054928,-0.052327,-0.067591,0.012738,-0.058731,-0.019401,0.047217,0.060054,-0.005114,-0.067708,0.040945],"category":"KYC Fraud","source":"seed_minilm"},{"embedding":[-0.000846,-0.126655,-0.028271,-0.147805,0.092819,0.04301,0.049271,-0.017325,0.04214,-0.000556,0.043167,0.0212,-0.065954,-0.012591,0.036619,0.013823,0.089323,0.010419,-0.030833,-0.014408,0.04976,-0.100172,0.022428,0.018876,-0.018779,-0.02604,0.0734,0.122153,0.012067,-0.06042,0.030319,0.017103,0.032358,-0.024732,0.035143,-0.065339,-0.027608,-0.039904,-0.026442,-0.073607,-0.016192,0.001388,0.0263,-0.02983,0.048528,-0.015334,-0.041,-0.131524,0.067491,-0.01594,-0.05113,-0.000881,-0.023735,0.026658,-0.075517,0.016572,-0.005567,0.0297,0.087084,0.067325,-0.00856,0.020408,-0.000937,0.081115,-0.030848,0.056519,0.009501,-0.024287,-0.015,-0.010248,-0.038505,0.017878,-0.088577,0.054288,-0.081089,-0.064109,0.014807,-0.018033,0.012725,-0.041627,0.061678,0.014528,0.042389,-0.023444,-0.040803,0.053111,-0.030492,0.006361,0.016712,0.013342,-0.000405,0.074713,0.028066,-0.120412,0.053247,-0.074783,0.005935,-0.054474,-0.066168,0.048686,-0.013202,-0.000183,0.046453,0.038584,-0.023293,-0.039983,0.049406,0.001705,0.025722,0.022405,-0.05589,0.013986,0.028865,-0.014911,0.015521,0.061151,-0.03851,0.037172,0.031151,-0.033671,0.027891,-0.043371,-0.026189,-0.033524,0.015114,-0.031732,-0.0131,0.0,0.03785,-0.021583,-0.029496,-0.00878,0.048291,0.009332,0.050131,-0.038674,-0.108411,0.000734,0.034429,-0.091999,0.005899,-0.084058,0.027603,0.012759,0.004373,0.050893,0.054957,0.074406,0.077638,-0.042972,0.042242,-0.022294,-0.061975,-0.02288,0.096207,-0.029521,0.133059,0.045899,-0.020268,0.021078,0.038104,0.012681,0.042446,-0.011133,-0.052786,-0.047534,-0.047746,-0.022786,-0.027443,-0.031381,-0.120294,-0.04577,-0.079612,-0.022476,0.06163,0.044267,-0.003478,0.058529,-0.071153,0.003701,-0.114518,-0.095634,0.004118,-0.011174,0.014728,0.002872,-0.016229,-0.006023,0.071727,-0.005904,-0.023971,0.007385,-0.044665,-0.079054,0.01438,-0.042491,0.010624,-0.006831,-0.039383,-0.03578,0.048208,-0.016304,-0.054734,0.020087,-0.066278,0.024873,-0.053206,0.025979,-0.043006,-0.016225,0.030973,0.061434,0.068785,0.045116,-0.011287,-0.021758,-0.024671,0.02278,-0.027352,-0.009624,0.053494,0.054162,-0.046262,-0.0,-0.013438,-0.026583,-0.026114,-0.032726,0.024924,-0.018755,0.064041,0.053145,0.082958,-0.021182,0.014866,-0.063715,-0.044366,-0.044192,-0.010536,-0.068513,0.012021,0.021214,-0.1183,0.006429,-0.042599,0.069765,0.123656,0.005237,0.018492,0.022129,0.04345,0.174773,-0.029737,0.006084,0.060248,-0.092041,-0.155509,-0.021748,-0.020416,-0.02214,0.078972,0.058726,-0.026064,0.073058,0.049045,0.05472,-0.076654,0.000187,-0.022051,-0.077305,-0.036108,-0.055333,-0.024552,-0.065386,-0.030903,-0.056607,0.076786,0.016206,-0.044269,0.063781,0.09005,0.098171,0.055017,-0.010859,0.046912,0.009336,-0.04218,0.028904,0.087531,0.03243,0.090794,0.089972,0.058033,-0.015021,0.021487,-0.019504,0.077114,0.139625,0.11114,-0.065208,-0.068618,0.010734,0.016181,-0.002456,-0.009135,0.01383,-0.103131,-0.01489,0.105548,0.023132,0.066765,0.043451,0.052283,-0.073982,-0.006388,0.013542,-0.044113,0.082066,0.008731,-0.0,-0.054098,-0.067179,-0.055266,0.067126,0.01768,0.0079,-0.00953,-0.043532,0.049862,-0.025354,0.006916,0.036941,-0.02771,0.009174,-0.038738,-0.019985,-0.007391,0.049518,0.018617,-0.018778,0.041343,-0.06778,0.066561,-0.022453,-0.049117,-0.002656,-0.010936,0.061266,-0.006506,0.007143,-0.043785,0.028204,-0.00292,-0.131172,0.001935,0.053649,-0.050488,0.031911,0.007919,0.033347,-0.046786,-0.04824,0.073199,-0.015485,-0.012295,0.053085,-0.045927,-0.01812,0.059832,0.006635,-0.014207,-0.028471,0.004455,0.095867,0.032995,-0.0481,0.089457,-0.040074,-0.048645,0.061009,0.085588,0.026937,0.006788,-0.029959],"category":"KYC Fraud","source":"seed_minilm"},{"embedding":[-0.0038,-0.079126,-0.015443,-0.039712,-0.040807,-0.001136,0.012016,-0.073065,-0.022604,0.049612,0.067299,0.051716,0.032769,-0.108795,0.046458,0.030867,-0.004398,0.006793,-0.035036,-0.01754,-0.005237,-0.002018,-0.013961,0.017513,0.008403,0.01347,0.00702,0.02771,-0.054448,-0.040305,0.002926,0.025975,-0.011994,-0.105273,0.088943,-0.011824,-0.022292,0.079673,0.008972,-0.085781,-0.009839,-0.113484,-0.021466,0.011913,-0.000511,0.085491,-0.028275,-0.016477,0.0215,0.04053,0.038456,-0.05463,-0.039912,0.021741,-0.024137,0.052601,0.028511,0.115267,0.1,0.000514,-0.031964,0.079236,-0.015388,0.05101,-0.003084,0.050215,-0.095921,-0.067203,0.036134,0.028925,-0.007157,-0.082405,-0.066995,-0.073472,-0.080023,0.035404,0.076311,0.058716,0.090981,0.041884,0.046405,-0.056374,0.082386,-0.076998,-0.009152,-0.027891,-0.020836,-0.022395,0.002475,0.014068,0.149509,0.009966,0.132039,-0.060436,-0.002394,-0.082647,-0.017622,0.02365,-0.064982,0.033588,0.068006,0.064415,-0.0242,0.03602,0.06935,0.014172,0.067992,0.048879,0.071714,-0.001744,-0.004107,0.013007,0.029016,-0.02286,0.006545,0.064586,-0.009084,0.03601,-0.001262,-0.040291,0.091263,0.086904,0.039089,-0.108259,-0.060151,0.016203,0.039,-0.0,0.002178,0.014428,-0.006721,-0.063145,-0.018516,-0.037534,-0.019472,-0.049751,-0.06302,-0.007629,0.008461,-0.051806,0.016986,-0.037448,-0.055473,-0.003686,0.016489,0.058569,0.112978,0.07173,0.032226,-0.04509,0.030051,-0.040696,-0.047482,-0.027248,0.045234,-0.00027,0.024131,0.024126,-0.055474,0.026943,0.016454,0.016737,-0.065443,-0.011079,-0.010245,-0.066184,-0.069212,-0.051494,-0.001384,0.026089,-0.022919,0.022495,0.046688,-0.000206,0.049476,0.011152,-0.046007,0.075236,-0.024094,0.041407,-0.123452,-0.014853,-0.076288,-0.015817,0.028092,-0.016355,-0.007487,-0.039454,0.0889,-0.049225,-0.030842,0.009457,-0.017719,-0.045938,0.040019,-0.02651,-0.104085,-0.02259,0.008306,0.004798,0.042907,-0.014774,-0.089351,-0.024459,-0.007198,0.070763,-0.040111,0.037479,0.128863,-0.102886,-0.045144,0.011131,0.02747,0.051053,0.010598,0.049147,-0.083484,-0.032031,-0.029767,-0.028446,0.003296,0.10012,0.028945,-0.0,-0.031554,-0.080934,0.00504,0.017112,0.02076,-0.069222,0.000453,0.070608,-0.015836,-0.013887,-0.019436,0.002224,-0.034748,-0.020421,0.004528,-0.045028,-0.032614,-0.005455,-0.051924,0.043191,0.014492,0.040511,0.000729,0.048414,-0.034829,0.042193,-0.074402,0.053301,0.005377,0.053798,-0.001796,-0.075215,-0.026802,0.068261,-0.041004,-0.100387,-0.002288,-0.044598,7e-06,0.017581,0.096095,0.101713,-0.040262,-0.049652,0.058766,0.053592,0.069223,-0.037835,0.034691,-0.010701,-0.041697,-0.006742,0.027186,0.06256,-0.023892,0.062491,0.130193,-0.002037,0.032593,-0.033742,-0.018213,0.007115,0.052013,0.028221,0.098968,0.055889,0.106771,0.017704,0.081377,-0.053084,-0.034511,-0.057605,0.033518,0.036748,0.046198,-0.037906,-0.048114,0.015375,-0.046007,-0.025692,-0.038666,-0.007028,-0.026542,0.013501,0.023062,-0.085648,0.049332,-0.068644,0.098449,-0.045326,0.031898,-0.092187,-0.076748,0.104093,-0.042348,-0.0,0.012977,-0.017751,-0.025554,0.036047,0.108909,0.011866,-0.021237,-0.039293,-0.085378,-0.007246,0.033358,0.080702,-0.034667,0.015877,0.01248,-0.026514,-0.00071,-0.065607,0.021883,-0.054002,-0.051834,-0.030466,0.078774,0.002493,-0.036679,-0.032084,0.073894,0.129712,0.082126,-0.065159,-0.097646,0.017168,-0.002278,-0.024616,-0.050976,-0.008754,0.007276,-0.04413,-0.018359,0.075324,-0.046533,0.001847,0.064713,0.011197,0.021587,-0.007846,-0.095629,0.048228,0.020046,-0.031853,-0.08777,-0.000151,0.031256,0.030727,0.03568,-0.010119,-0.087343,-0.003601,-0.031395,-0.055324,0.034105,0.002078,-0.049815,-0.128151],"category":"KYC Fraud","source":"seed_minilm"},{"embedding":[-0.02242,-0.046337,-0.01099,-0.006228,-0.00383,-0.037879,0.001852,-0.085464,-0.02849,0.041767,0.070193,-0.047781,2.7e-05,-0.059346,0.010588,0.034917,-0.019046,0.007742,-0.030047,-0.01047,-0.056293,-0.049034,-0.017735,-0.029323,-0.017405,-0.023327,0.059446,0.040154,-0.082024,-0.014502,-0.029625,0.028411,-0.049875,-0.044311,0.08071,-0.001219,-0.03045,0.073864,0.039972,-0.101042,0.023236,-0.09744,-0.012485,-0.015422,0.045619,0.112001,0.038957,-0.017895,0.000247,0.008592,0.006348,-0.074255,-0.052222,-0.05662,-0.009062,-0.000615,-0.025769,0.084312,0.056494,-0.000744,0.03179,0.10999,0.026929,-0.002962,0.032764,-0.008861,0.00618,-0.002347,0.075996,-0.007452,0.008413,-0.044566,-0.034305,-0.080966,-0.059269,0.051669,0.004826,-0.01793,0.055904,0.019089,0.003751,-0.084456,0.037621,-0.078549,-0.034555,0.014448,0.033706,-0.0381,0.00761,0.037025,0.083865,0.043492,0.087845,-0.047341,0.026238,-0.031273,-0.029058,0.056234,-0.083703,0.014626,0.106987,0.100913,0.005486,0.051149,-0.036002,-0.101875,0.105051,-0.015127,0.034929,-0.045268,-0.064618,0.041246,-0.018826,-0.061017,-0.048724,0.028627,-0.038047,-0.000855,0.012558,0.090417,0.063194,0.061404,-0.024661,-0.020665,0.014,0.057462,0.006711,0.0,-0.070237,0.01607,0.06358,-0.033433,-0.045143,-0.085506,0.000577,-0.11202,0.000348,-0.027705,-0.002881,-0.052931,0.000764,-0.061606,-0.071891,-0.073152,-0.010979,0.040759,0.025678,0.114092,0.07137,-0.075859,0.040951,-0.020239,0.0076,0.001977,0.005367,0.045424,0.101742,0.044868,-0.034462,-0.049472,-0.008727,-0.03142,-0.064342,-0.017962,-0.043359,-0.064533,-0.021936,-0.064577,-0.042937,-0.018944,-0.007676,0.02633,-0.034066,0.051053,-0.096432,0.083747,-0.017017,0.005009,-0.04009,-0.015879,-0.143752,-0.020187,-0.015173,-0.014114,0.032997,-0.053425,-0.037164,-0.017503,0.03744,-0.078465,-0.081843,0.007852,0.027184,-0.018388,-0.045218,-0.027623,-0.046457,-0.034546,0.009494,0.038241,0.062559,0.034865,-0.12766,-0.003995,-0.088366,0.015621,-0.07376,0.096368,0.053978,-0.013428,-0.045274,-0.062175,0.035058,0.069534,0.013554,0.02416,0.018368,0.017544,0.0037,0.038241,0.023335,0.042178,0.031802,-0.0,-0.014793,-0.04391,-0.04025,0.024875,0.013645,0.075109,0.018,0.075641,0.041409,0.01082,-0.041717,0.052362,-0.028533,-0.02539,0.012275,0.024647,0.039382,0.024563,0.025301,0.121274,-0.027036,0.03318,-0.031898,0.079108,-0.039662,0.04851,-0.086296,0.045063,-0.016257,0.045123,-0.008008,-0.080617,-0.032358,0.056684,-0.010379,-0.109508,0.056061,-0.078721,0.023145,0.06148,0.115475,0.016082,-0.081393,-0.011467,0.04263,-0.018085,0.089278,0.005532,0.018842,-0.029114,0.031291,-0.043173,-0.001248,-0.029046,0.039213,0.096973,0.03192,0.028099,0.045944,-0.059613,-0.051858,0.008108,0.03126,0.047266,0.048138,0.079583,0.127892,0.014327,0.037088,-0.098434,-0.013712,-0.041461,-0.022913,-0.021602,0.012693,-0.021993,0.0036,0.085623,0.012537,-0.024871,0.001811,0.051636,-0.014569,-0.023558,0.076105,-0.058858,0.010595,0.000912,0.071859,-0.097806,0.003452,-0.098341,-0.026552,0.076288,-0.024473,-0.0,0.033815,-0.09329,-0.023675,0.026827,0.081375,-0.008439,-0.046667,0.093908,-0.017657,0.014638,0.042521,0.076662,-0.038004,-0.004761,0.015073,0.008802,-0.022791,0.035979,0.007953,-0.10615,-0.07757,0.029346,0.041843,-0.023634,-0.026174,0.008453,0.034369,0.095663,0.035141,-0.138813,-0.09199,-0.019362,0.008357,-0.0861,-0.025603,0.04027,0.054672,0.074363,0.018265,0.089052,-0.054451,-0.040249,0.057809,-0.014178,0.018608,0.066966,-0.070183,-0.012862,0.038921,-0.034564,-0.10796,0.017998,0.071725,0.068614,-0.016163,0.017704,-0.046003,-0.033002,-0.014453,-0.017245,0.059348,-0.020411,-0.073967,-0.000602],"category":"KYC Fraud","source":"seed_minilm"},{"embedding":[-0.031215,-0.049445,-0.024858,-0.026361,-0.009426,0.03372,0.029001,-0.069672,0.0107,0.045087,-0.006385,-0.029119,-0.013014,-0.01231,0.005484,0.0337,-0.014174,-0.028407,0.005078,-0.011612,-0.111516,0.01738,-0.029944,0.006446,0.061966,-0.032562,0.012376,0.02701,-0.0959,-0.02906,-0.020605,-0.016507,-0.106066,-0.043767,0.025992,-0.063884,-0.091671,0.100554,0.070222,-0.100897,0.04375,-0.065744,0.045857,0.010066,0.064869,0.145514,-0.021013,-0.013962,0.015422,0.059037,0.081924,-0.026623,-0.012899,-0.007125,-0.060254,0.010263,-0.041393,0.063657,0.037714,0.010413,-0.042438,0.100549,0.007649,0.023069,0.034075,-0.034207,-0.046978,0.050594,-0.036574,0.049178,0.013263,-0.029019,-0.075711,-0.046192,-0.024532,0.073844,0.015336,0.019207,0.07133,-0.051464,-0.041859,0.025867,0.020276,0.037524,0.028236,-0.003419,0.007839,-0.0186,-0.087566,-0.052803,0.116564,0.053304,0.096843,0.019064,0.052135,-0.045234,-0.057374,0.057215,-0.082541,0.017858,0.016443,0.077787,-0.072565,0.049306,-0.043508,-0.037846,0.046474,-0.012976,0.090393,-0.007421,0.002723,0.017878,-0.027943,-0.076532,-0.051797,0.043929,-0.114594,-0.020533,-0.023375,0.013612,-0.053764,0.004355,-0.035813,-0.012925,-0.101855,-0.032603,0.098455,0.0,-0.06181,0.019508,0.032552,-0.036193,-0.021542,-0.089302,0.050562,-0.083659,-0.031149,0.008922,-0.041937,-0.048534,-0.009069,-0.067823,-0.072262,-0.018236,0.070903,0.019187,0.044685,0.109779,0.01963,0.00326,0.010941,0.004847,-0.01096,0.028206,0.051144,-0.02558,-0.01243,0.031481,-0.007454,0.027426,-0.020119,-0.022288,-0.06529,-0.035718,-0.013871,-0.037993,-0.053974,-0.043188,-0.029239,-0.02427,0.027705,0.010275,0.062532,0.072273,0.013007,0.085458,-0.075886,0.057778,-0.055105,0.005193,-0.081282,0.054952,-0.02125,-0.034572,-0.017819,-0.047653,0.016184,-0.034033,0.069485,-0.058557,-0.112164,-0.031784,-0.069012,0.028811,0.053822,-0.08453,-0.026645,-0.004489,0.05346,-0.011053,0.026017,0.074893,-0.055992,0.010199,-0.066444,0.066831,-0.042859,0.021704,0.028706,0.033585,0.015687,0.030296,0.05716,0.050117,0.000662,0.042405,-0.031984,0.079096,0.056806,0.033305,0.113614,0.079976,0.006038,-0.0,-0.063131,-0.02221,-0.090564,-0.033873,-0.015637,0.011501,0.09972,0.059419,0.043587,0.064093,0.0446,0.048808,-0.015238,-0.026866,-0.026314,-0.018997,-0.033936,0.082511,0.048715,0.021289,-0.017657,0.116996,0.01652,0.021553,-0.014364,0.057652,-0.059171,0.068645,0.004746,-0.008064,-0.019584,-0.016361,-0.090899,0.082828,-0.022871,-0.08664,0.06708,-0.088633,-0.017142,-0.022756,-0.036946,0.068817,-0.022425,-0.007795,0.092664,-0.050016,0.009796,0.040816,-0.002809,0.016418,0.010037,-0.027492,0.10558,-0.021076,0.00832,0.101945,0.088477,-0.069643,0.025484,-0.017586,0.025924,0.055278,0.049611,0.087185,0.101792,0.051532,0.038736,0.064397,0.081314,-0.051647,-0.034459,-0.087455,-0.028451,0.013019,0.039823,-0.046333,0.027852,0.053178,0.010284,0.032793,-0.043016,0.028863,0.046108,-0.041031,0.047983,-0.021952,0.05441,-0.052857,0.005133,0.000417,-0.080806,-0.085788,0.001629,0.088089,-0.076377,-0.0,0.024552,-0.044742,0.001441,-0.012427,0.053141,-0.046942,-0.074382,0.037626,-0.01329,-0.04658,-0.012927,0.023273,-0.023138,-0.013005,-0.028067,-0.002815,-0.035631,-0.006215,-0.016679,-0.116557,-0.003298,0.045375,0.042946,-0.051,-0.067537,0.018833,0.049728,0.133475,0.018,-0.029191,-0.110619,-0.004584,0.08734,-0.068253,-0.045025,0.035972,0.010934,0.006748,0.043927,0.0141,-0.029442,-0.026048,0.124074,-0.033444,0.003711,-0.029657,-0.016005,-0.024783,0.048748,-0.07247,-0.065517,0.012052,0.045696,0.01759,-0.024385,-0.065913,-0.063569,-0.069309,0.020064,-0.018885,0.027633,-0.055041,-0.071426,0.013494],"category":"KYC Fraud","source":"seed_minilm"},{"embedding":[-0.066546,0.047612,-0.027046,-0.044314,-0.064235,-0.02866,0.092707,0.027233,-0.041937,-0.0725,0.08712,-0.026255,-0.006878,0.013707,-0.006989,-0.014716,0.050651,-0.020219,0.002986,0.030488,-0.008298,0.043851,-0.035456,-0.020129,0.027428,-0.083907,0.047823,0.023995,-0.003564,-0.017947,0.052061,0.036825,0.016087,-0.010766,-0.001699,-0.011012,0.06465,-0.032354,0.01765,0.025833,0.015278,0.02393,-0.055117,-0.031137,0.066126,0.004663,0.005233,0.053549,0.017249,0.031716,-0.033921,0.060217,-0.043149,0.046971,-0.025358,-0.007369,0.029708,-0.030949,-0.033967,-0.031116,0.043704,0.036016,0.043488,0.026299,0.044635,0.027632,0.016106,-0.01298,-0.0221,-0.008095,0.041437,-0.016656,-0.089625,0.021534,-0.090647,0.021101,0.011711,-0.017889,-0.018119,-0.015378,0.001381,0.033846,-0.043766,-0.057863,-0.025425,-2.7e-05,0.060447,0.110214,-0.002867,-0.056774,0.03138,0.053995,0.029498,-0.062131,-0.025988,-0.02347,-0.04171,0.009468,-0.056419,0.006495,0.043183,0.052642,-0.086754,0.025251,-0.07806,-0.003421,0.02767,0.020853,-0.013061,-0.018232,-0.041978,0.000615,0.015496,-0.024691,-0.058899,0.086588,-0.065112,0.05706,0.058867,0.015242,0.020464,0.019542,-0.102555,0.020219,-0.053077,-0.05606,0.073875,0.0,-0.033139,0.00715,-0.061953,-0.09769,0.053893,-0.002817,0.009806,-0.024648,-0.075035,-0.002844,-0.05457,-0.055607,0.012216,-0.024194,-0.096893,-0.04873,0.024559,0.113009,0.101831,0.036901,0.023095,0.003604,0.011774,0.038113,-0.026163,0.117066,-0.052584,-0.032424,0.128912,-0.013253,0.137103,-0.02228,-0.044372,0.034536,0.032483,0.066159,0.003892,-0.043393,-0.003826,-0.040418,-0.041137,0.033958,-0.046032,0.003836,-0.033458,0.018446,-0.054455,0.039015,0.063279,0.031408,-0.064261,-0.034043,-0.126336,-0.039539,-0.032094,-0.093349,-0.02065,0.011525,-0.033995,-0.031789,0.061819,-0.049488,-0.047562,-0.03593,-0.09394,-0.049107,0.033233,-0.084335,-0.004085,-0.03256,-0.054593,0.061933,0.071146,0.095091,-0.026963,0.028097,0.045623,0.02988,0.080972,0.040645,-0.091196,-0.01268,0.076781,0.015887,0.054873,0.071344,-0.056358,0.10405,-0.005464,0.085611,0.03979,0.076952,0.023228,0.017721,0.027651,-0.0,-0.058282,-0.015078,-0.090369,-0.045241,-0.062811,0.039397,-0.00158,0.03096,0.022717,0.052109,-0.03405,-0.038764,0.135268,-0.088432,0.031,-0.098353,0.059119,0.139694,-0.015835,-0.037192,-0.035776,0.043433,0.033026,0.021373,0.034813,0.07817,-0.020385,0.036014,-0.017281,-0.011463,0.041682,-0.035701,-0.105483,0.013061,-0.034411,-0.031895,0.064294,0.056706,0.002012,0.012767,-0.001073,0.038409,-0.011173,-0.008663,-0.054129,-0.087232,-0.012234,-0.065407,0.033791,0.010103,0.067474,0.008141,0.089191,-0.056601,0.001538,0.165143,0.090918,-0.004442,0.035762,-0.055096,0.029942,0.069604,-0.014973,0.049702,0.026954,0.075761,0.012328,-0.007122,0.024388,-0.081944,-0.017144,-0.061595,0.030128,0.006039,0.058033,-0.01674,-0.104391,-0.003818,0.051629,-0.030806,-0.016543,0.049363,0.06016,0.080358,-0.022319,-0.06155,0.054691,0.060796,0.071323,-0.07313,-0.020872,0.005216,-0.040035,-0.028414,0.017708,-0.0,0.04255,-0.111331,0.014373,-0.014164,0.004231,-0.018259,0.027126,0.001784,-0.043602,-0.014119,-0.016142,-0.023451,-0.113754,-0.034813,0.023444,-0.10451,0.021509,-0.059922,-0.050465,-0.094425,-0.010558,0.00303,0.080822,-0.016097,-0.032332,0.012192,0.016763,0.159688,0.098777,-0.083166,-0.010043,-0.019152,-0.079628,-0.008007,-0.049678,-0.029273,0.022213,0.072089,-0.01077,0.03206,-0.044383,-0.068093,-0.015366,0.020309,0.063031,0.013952,-0.072108,-0.056219,-0.02837,-0.027575,-0.005848,-0.060092,0.062018,0.009492,-0.075444,-0.076369,-0.046822,-0.020819,-0.044653,0.059768,0.020487,0.000286,-0.034005,-0.027417],"category":"OTP Phishing","source":"seed_minilm"},{"embedding":[-0.044083,-0.036551,-0.039552,-0.06551,-0.026342,-0.056062,-0.006893,-0.034383,-0.053853,-0.020333,0.052548,0.0039,0.029288,-0.023981,0.006421,0.053175,0.035713,-0.073149,0.029247,0.037414,0.010909,-0.022111,-0.023709,-0.040203,0.046278,-0.054848,0.024431,0.022138,-0.011256,-0.035157,0.028283,0.051747,-0.034104,-0.080342,0.016292,0.074726,0.031892,-0.01349,0.06395,-0.071265,0.016208,-0.007723,-0.059267,-0.005324,0.065314,0.040371,-0.026122,0.047435,0.057184,0.007021,-0.007841,0.069244,-0.05847,0.065792,-0.051663,0.098334,0.010612,0.009276,-0.04708,-0.003172,0.019561,0.037483,-0.006989,-0.001059,0.047999,0.011368,0.013197,-0.026619,8.8e-05,-0.045424,-0.023579,0.004694,-0.096685,0.024994,-0.031893,0.028138,0.043253,0.018433,0.020879,-0.081243,-0.05239,0.015896,-0.004675,-0.05148,-0.020775,-0.023935,0.046699,0.09731,-0.033778,-0.049667,0.077729,0.025375,-0.02884,0.019953,0.000803,0.005989,-0.034204,0.048126,-0.065494,-0.00388,0.011925,-0.006772,-0.085202,0.041942,-0.083981,-0.051551,0.100768,-0.011242,0.015134,-0.008217,0.042865,0.002001,0.098459,0.027037,-0.010684,0.11269,-0.167852,0.03452,-0.021911,0.023458,0.018013,-0.002848,-0.033537,0.000734,-0.096302,-0.037483,0.116623,0.0,0.009322,0.054142,-0.056509,-0.024177,-0.009789,0.03603,-0.008833,-0.012991,-0.041427,-0.064646,-0.07651,-0.084987,0.009262,-0.032904,-0.085538,-0.072279,0.053303,0.071568,0.13217,0.054623,0.035204,-0.057168,-0.036334,-0.035362,0.005722,0.087477,-0.005738,-0.031719,0.113859,0.026235,0.062778,-0.021427,-0.045917,-0.001591,0.044353,-0.003235,0.01642,-0.050911,-0.066065,-0.04206,-0.012632,0.025499,-0.108049,0.01535,-0.055594,-0.013237,0.039692,0.045342,0.02875,0.076919,-0.100838,-0.048613,-0.083397,-0.088027,-0.013082,-0.013004,-0.035652,-0.019773,-0.016339,0.052262,0.099918,-0.026566,0.024898,-0.026244,0.016388,0.011358,0.025333,-0.02709,0.032332,-0.031533,-0.047897,0.013194,0.047355,0.076967,-0.025,-0.016366,0.066925,-0.01387,0.004741,-0.010259,-0.048323,-0.002959,0.022978,-0.024069,0.076889,0.078615,-0.034645,0.054667,-0.014607,0.102601,0.024147,0.084572,-0.001952,0.035943,-0.000926,-0.0,-0.003242,-0.012884,-0.058984,-0.011903,-0.020965,0.018615,0.04537,0.112271,0.041304,0.137456,0.033506,-0.031501,0.031608,-0.086785,-0.013405,-0.11325,0.049692,0.055993,-0.035008,-0.002968,-0.009979,0.075447,0.009064,-0.009733,0.008483,0.174073,-0.099621,0.041598,-0.043678,0.023717,0.047256,-0.039432,-0.087354,0.02017,-0.000224,0.022969,0.092579,0.025959,-0.009863,0.034564,-0.043372,0.070219,-0.076865,-0.085287,-0.02888,-0.092848,-0.007597,-0.084178,-2e-06,-0.008625,0.067942,-0.028716,0.083661,-0.053139,0.065114,0.034416,0.085611,0.022198,0.007145,-0.062699,0.074627,0.003083,0.038206,0.034293,0.01785,0.057277,0.107085,-0.028504,0.089934,0.010662,-0.104051,-0.01445,0.050193,-0.014336,0.019445,0.038476,-0.052777,0.015717,0.017026,-0.059583,-0.035386,0.048724,-0.009379,0.074419,-0.015434,-0.058807,0.051287,0.062295,0.064988,-0.065538,-0.021806,-0.021102,0.008609,0.021172,0.02501,-0.0,0.032816,-0.008395,-0.021307,0.021122,0.005963,0.040537,-0.032872,-0.07028,0.019308,-0.075117,-0.008601,0.003438,-0.06754,0.00246,-0.028913,-0.091567,0.003769,-0.074761,-0.049363,-0.129031,0.025345,-0.000679,0.041984,0.016379,0.021413,-0.017229,0.047935,0.106811,0.082337,-0.121135,-0.009853,-0.026806,-0.068475,0.011306,-0.002764,0.029195,0.001729,0.088311,-0.036526,0.083598,0.016741,-0.055006,0.003227,-0.019184,0.063309,-0.019191,-0.052307,-0.034459,-0.039865,0.000229,0.021553,-0.053293,0.048801,0.030088,-0.006736,-0.067509,-0.104481,-0.022727,-0.039157,0.030685,0.002025,0.033923,-0.077774,-0.049371],"category":"OTP Phishing","source":"seed_minilm"},{"embedding":[-0.11439,0.029067,0.082606,-0.01072,-0.061533,-0.04504,0.073427,-0.027957,0.012989,0.014919,0.038845,-0.037723,-0.003425,-0.03443,-0.08988,-0.036823,-0.050615,-0.014781,-0.059431,0.030929,0.062674,0.008813,0.017221,0.01431,0.044924,-0.104869,-0.091042,0.065154,-0.024032,-0.03683,0.073125,0.166582,0.003611,-0.014367,0.009937,0.008128,-0.029507,-0.060246,-0.033162,0.018251,-0.006443,0.022282,-0.024495,-0.016521,0.090784,-0.019387,-0.00925,-0.0049,0.059745,0.039639,0.013804,0.050093,-0.03798,-0.00947,-0.084661,0.040261,0.011631,0.052758,0.106854,-0.094023,0.062308,-0.035336,-0.02862,0.018607,-0.002243,-0.054006,-0.072251,-0.021986,-0.022543,-0.018331,0.059307,-0.020824,0.041525,0.015414,0.02576,0.052253,0.023477,0.014263,-0.006023,0.081296,-0.010087,-0.067905,-0.028846,0.032797,0.078253,-0.05874,-0.020569,0.090863,0.00841,-0.10133,-0.030904,0.075028,0.00022,-0.008028,-0.001056,-0.014998,0.010669,-0.077006,-0.103528,0.049558,0.04414,0.048182,-0.012514,0.020013,0.035777,-0.000311,-0.022787,0.060772,0.056838,-0.02392,-0.019598,-0.053469,0.048897,0.048462,0.01394,0.058815,-0.071331,0.028791,0.106596,-0.119859,-0.007229,0.010971,-0.096764,-0.077997,-0.12565,-0.09993,0.04534,-0.0,0.020055,0.050576,-0.006366,-0.045648,-0.011623,-0.017584,-0.065273,-0.04227,-0.037318,-0.013362,-0.018782,-0.05913,-0.007724,0.071454,-0.095481,0.009276,-0.003067,0.046053,0.032658,0.042662,-0.048174,-0.088022,-0.049586,-0.030116,0.043182,0.034182,0.064027,-0.042546,0.113441,-0.012722,0.069299,-0.07786,0.072149,0.020285,-0.033968,0.035945,0.051298,-0.023566,-0.02718,-0.023572,0.046227,-0.035749,-0.061668,-0.020007,0.006601,0.032983,-0.038319,-0.063224,0.070019,0.062175,-0.05196,0.024283,-0.03026,-0.028561,-0.069366,0.011987,-0.010476,0.073072,-0.021976,-0.122965,0.004725,-0.072968,-0.017415,-0.04004,-0.058489,-0.05395,-0.053442,0.006371,-0.03076,0.098711,-0.089082,0.054674,0.084197,0.077478,0.011436,0.030239,-0.037836,-0.013442,-0.048392,0.009599,-0.031739,-0.024736,-0.04388,0.059377,0.067008,0.001716,0.089777,-0.082425,0.04213,0.066509,-0.045196,-0.036359,0.066357,-0.028194,-0.006097,-0.0,-0.019389,0.006292,0.022674,-0.002524,0.003792,-0.033217,0.079177,0.072405,0.064319,-0.019748,0.009235,-0.0391,0.06328,-0.011428,0.060907,0.041313,0.001878,0.032476,-0.01816,0.007067,-0.031454,-0.002549,0.062984,-0.000463,-0.078223,0.055524,0.007952,0.013362,0.005456,-0.030833,0.042202,-0.009333,-0.11691,0.073428,0.051424,-0.039719,-0.010677,-0.027756,0.008756,-0.020804,0.044557,-0.003102,0.022462,0.034841,0.000244,-0.106728,0.08955,-0.04607,-0.004547,-0.008805,0.020552,0.008865,0.048941,0.018843,-0.010597,0.076327,0.125896,-0.049881,-0.04254,0.004357,0.055084,0.0057,-0.007903,0.010094,0.010667,0.013545,0.052241,-0.022157,0.057981,0.01163,0.000668,0.054933,0.04856,0.084614,0.137118,0.027679,-0.127416,0.026226,0.021763,-0.027157,0.048733,0.013293,0.033958,0.023574,0.056509,-0.085556,0.009412,0.028982,-0.048937,-0.065564,-0.051153,-0.034292,0.035746,0.039014,0.023532,-0.0,0.033288,0.035314,0.025152,-0.047605,0.04781,-0.008608,-0.029515,-0.045323,6.1e-05,-0.143168,-0.049361,-0.009268,-0.082008,0.050586,0.04964,-0.069548,-0.037766,-0.006861,0.007979,-0.018598,-0.007317,0.035898,0.010846,-0.031128,-0.032486,0.052419,0.107436,0.118708,0.057105,-0.038304,-0.003753,0.014669,-0.048485,-0.043717,-0.060308,-0.063349,-0.009583,-0.036989,0.063101,-0.03591,0.069437,-0.076444,0.044979,-0.04924,-0.003898,-0.024711,0.060005,-0.0132,-0.022264,-0.0333,-0.116595,-0.041625,0.015599,-0.062307,0.045495,-0.086101,-0.006915,0.005395,0.025177,-0.034496,0.051844,-0.002925,-0.046906,0.002814],"category":"OTP Phishing","source":"seed_minilm"},{"embedding":[-0.117037,0.007167,-0.027553,-0.019546,-0.0136,-0.018373,0.0661,-0.015214,-0.034505,-0.009065,0.029548,-0.030566,0.059889,-0.014675,0.03324,-0.016585,-0.001166,-0.058528,0.036254,-0.005597,0.026337,-0.003749,-0.002605,0.021385,0.063347,-0.138336,-0.046426,0.053808,-0.032576,0.01748,0.057817,0.079836,0.05643,-0.015077,0.013728,-0.040663,-0.015634,-0.02091,0.00274,-0.026937,-0.066477,-0.032244,-0.074437,-0.001958,0.050989,-0.049076,-0.066068,0.091802,0.015954,-0.004328,0.065226,0.014246,-0.015191,0.042525,-0.091674,0.040614,0.001469,0.06635,0.059793,-0.051298,0.019124,0.009173,-0.032763,0.021219,-0.016815,-0.010719,-0.055199,-0.031495,0.019476,-0.054549,0.00427,-0.040173,0.001294,0.010094,-0.017648,0.002457,-0.02792,0.005458,0.059111,0.054651,-0.060621,-0.032332,0.013454,0.06658,0.051313,0.061972,-0.011279,0.080068,-0.02705,-0.084021,0.056102,0.04592,-0.002438,0.007577,-0.026301,0.039998,-0.051846,-0.034287,-0.084237,0.027531,-0.019908,0.044781,-0.057131,0.020611,0.017685,-0.012072,0.009226,-0.033577,0.07336,-0.021759,-0.03339,-0.071263,0.051883,0.059391,-0.081861,0.105997,-0.020659,0.134818,0.044257,-0.043334,0.037906,-0.012854,-0.067769,-0.047353,-0.104475,-0.069696,0.097493,0.0,0.045275,0.084711,-0.008846,-0.039532,-0.033428,-0.051438,0.0092,0.011677,-0.054578,-0.002675,-0.012234,-0.011673,0.017321,-0.013897,-0.054636,-0.024826,-0.016037,0.026329,0.120663,0.051802,-0.013677,-0.130526,0.021768,-0.032118,0.064139,0.049947,0.007929,-0.003993,0.074347,0.020147,0.074349,-0.079158,-0.06743,0.014748,-0.047872,-0.020137,0.064769,-0.013881,-0.048076,-0.055291,0.020765,0.011183,-0.103275,0.00426,-0.016158,0.010038,0.014828,0.011339,0.057035,0.133069,-0.080711,-0.011245,-0.130861,-0.067329,-0.037119,-0.070108,0.022064,0.051803,0.016072,-0.111653,0.044869,-0.062194,-0.008746,-0.016291,-0.068109,-0.031035,-0.043767,-0.089556,-0.04096,0.060146,-0.07709,0.03514,-0.012498,0.041487,-0.058707,0.032807,0.01591,0.047207,-0.012385,0.013468,-0.090537,0.006893,-0.017721,0.044247,0.139316,0.075201,0.009192,-0.059423,0.013639,0.038111,-0.025355,0.025935,0.067705,0.029963,-0.001801,-0.0,-0.042893,-0.052909,0.012403,-0.049409,-0.004547,-0.02767,0.035019,0.021543,0.099236,0.049837,-0.015794,0.053434,0.054088,-0.015689,0.106064,0.020268,-0.018259,0.112384,-0.060755,0.022837,-0.031843,0.02745,0.021013,-0.000287,-0.070585,0.030051,0.058491,0.041006,0.005258,-0.014796,0.069352,-0.052083,-0.149029,0.060612,-0.02454,0.008346,0.039914,0.004765,0.063978,0.071381,0.050582,0.031519,-0.028284,-0.006025,-0.03448,-0.144173,0.04515,0.021977,-0.053333,-0.056034,0.065712,-0.012081,0.043443,0.023538,-0.022318,0.098499,0.110253,0.006062,-0.019382,-0.086884,0.028016,0.003584,-0.059943,0.097815,0.001406,0.001805,0.072188,0.018063,0.050319,0.041964,-0.008856,-0.002561,0.071317,0.014066,0.082875,0.014201,-0.159916,0.052868,0.015045,-0.061417,0.010242,0.088477,0.012665,-0.03028,0.056716,-0.02167,0.040759,0.063431,0.027459,-0.065653,-0.026619,0.016462,0.004719,0.048149,0.040641,-0.0,0.051537,-0.064885,0.029456,-0.002156,0.070742,0.015448,-0.082114,-0.034767,0.020177,-0.125801,-0.036114,-0.026581,-0.058642,0.000508,0.009447,-0.06254,-0.00536,0.004798,-0.016717,0.008843,0.06223,-0.022097,0.067743,-0.049313,-0.036177,0.007611,0.038161,0.064199,0.015894,-0.078586,0.005337,-0.008229,-0.023362,-0.072083,-0.023369,0.024761,0.032933,-0.029228,0.018141,-0.017373,0.020108,-0.10419,-0.002653,-0.061929,-0.015184,0.038563,0.000477,-0.018031,0.009801,-0.03571,-0.076842,-0.104572,0.034988,-0.025499,-0.026156,-0.03016,-0.030004,-0.010905,0.020041,-0.005908,0.060579,0.067597,-0.060634,-0.038833],"category":"OTP Phishing","source":"seed_minilm"},{"embedding":[-0.097385,0.032248,0.063693,-0.044519,-0.004359,-0.036544,0.117882,-0.071772,-0.025577,0.01061,0.010081,-0.057565,0.028705,-0.017535,-0.067657,-0.005412,0.048779,-0.064069,0.014331,-0.012853,-0.031013,0.024812,-0.01209,0.027126,0.069453,-0.022763,0.032104,0.007692,-0.016241,0.004453,0.013486,-0.024577,-0.011303,-0.021934,-0.016478,0.004869,-0.024929,-0.009991,-0.0129,-0.005901,0.003792,-0.104678,-0.08088,-0.039365,0.056279,0.075559,0.053708,0.065914,0.043233,0.031151,0.003502,-0.043173,-0.056749,0.008878,-0.150433,0.002591,0.025819,0.023498,0.041525,-0.054081,-0.030004,-0.013434,-0.008654,0.008312,0.020575,0.034249,0.019833,-0.023869,-0.07157,-0.044956,0.08689,0.031959,-0.002432,-0.016939,-0.054288,0.008767,0.022315,0.006869,0.011935,0.013315,-0.051737,0.01291,-0.007322,0.037516,-0.029458,-0.020108,0.030395,0.063039,0.056185,-0.067931,0.04178,0.040863,-0.036304,-0.008589,-0.024377,0.016539,-0.047589,0.012406,-0.024725,-0.006516,0.056157,0.030156,-0.005001,-0.037607,0.007064,0.028745,-0.00461,0.025749,0.070554,-0.054998,-0.002653,-0.025301,0.035564,-0.010453,-0.011249,0.097295,-0.111523,0.011785,0.119211,-0.036955,0.04689,-0.003589,-0.11247,-0.09116,-0.093287,-0.081898,0.054529,0.0,0.025199,0.02021,0.045086,-0.035172,0.016271,-0.029323,0.030907,0.070124,-0.061223,-0.077395,-0.069756,-0.004876,0.047179,-0.005753,-0.137664,0.060388,-0.002884,0.099274,0.082858,0.102135,-0.005184,-0.010755,0.031886,-0.014118,-0.026084,0.125258,-0.033659,-0.029552,0.043491,0.024842,0.058212,-0.049075,0.016903,0.026397,0.017685,-0.000744,0.056372,0.004109,-0.020487,-0.066765,-0.008781,-0.029684,-0.038956,-0.002671,-0.071956,0.049879,0.011616,0.006265,0.084881,0.087776,-0.018688,0.008454,-0.072422,-0.067555,-0.031117,-0.014263,0.043728,-0.004505,-0.045564,-0.066073,0.054202,0.059082,0.016584,-0.065854,-0.053302,-0.045947,-0.032414,0.000649,0.033467,0.024807,-0.044805,0.075118,0.139934,0.094065,-0.024012,-0.035753,-0.008654,0.016786,0.001439,0.016755,-0.040917,-0.019881,0.059684,0.015577,-0.019527,0.138662,0.036841,0.030519,-0.003383,0.048877,-0.044993,-0.035145,0.01941,0.052369,0.024613,-0.0,-0.078457,0.031059,-0.052322,0.023719,-0.049008,0.004986,0.024789,0.040663,0.057916,0.207997,0.06395,0.044275,0.047662,-0.012889,0.033244,-0.097168,0.019389,-0.035165,-0.051448,-0.032287,0.020779,0.078572,0.062939,0.038984,0.081175,0.05245,-0.010382,0.01291,0.009224,0.069015,0.050904,0.032968,-0.043654,0.030502,0.048957,-0.085758,0.014094,-0.034072,0.087495,-0.029273,-0.04852,-0.003692,0.031538,0.000952,-0.006123,-0.138038,0.034963,-0.045335,0.006907,-0.02896,0.038337,-0.023944,-0.017822,-0.04554,-0.037654,0.102543,0.017225,0.036971,0.034038,-0.093255,-0.027274,-0.063912,-0.008247,0.040034,0.027464,0.033574,0.051292,-0.015893,0.153268,-0.000461,-0.112379,-0.027754,0.048621,-0.039219,0.048375,0.069733,-0.034758,0.010951,-0.025106,-0.00313,0.057801,-0.022648,0.095696,-0.033932,-0.014634,-0.061357,-0.019345,0.043567,0.049334,-0.045681,-0.053087,-0.030327,-0.075872,0.018226,-0.017822,-0.0,0.017163,0.046212,0.004036,0.032259,0.050968,-0.034379,-0.035898,0.00139,-0.045003,-0.044322,-0.033247,-0.058678,-0.073329,0.028288,0.021568,-0.078867,-0.060758,-0.082195,-0.044895,-0.059552,-0.005512,0.009544,0.006623,-0.073975,-0.04537,-0.064658,0.042215,0.128147,0.040313,-0.07998,-0.055533,0.018175,-0.137532,-0.045164,0.031444,-0.00026,0.038827,0.049723,0.005121,0.040135,0.000387,-0.043978,0.001655,-0.003125,0.027565,0.034367,-0.026287,-0.015684,0.015273,0.020041,-0.029553,-0.054797,0.00922,0.029519,-0.04344,-0.148997,-0.049318,-0.055188,-0.077907,-0.069578,0.058076,-0.001015,-0.045695,0.001543],"category":"OTP Phishing","source":"seed_minilm"},{"embedding":[0.012709,-0.064129,0.032955,-0.035356,0.00506,-0.012074,0.008953,-0.034773,0.035712,-0.030993,0.02973,0.063246,-0.082644,-0.003128,0.019031,0.06592,0.024333,-0.063735,0.024095,0.028238,0.084856,-0.025531,-0.011061,0.008945,-0.018418,-0.095677,0.094205,0.064432,-0.054636,-0.03439,-0.03586,0.088893,0.063736,-0.068939,0.037251,-0.002286,0.019932,-0.007148,0.085251,-0.062097,-0.026463,-0.041305,-0.038149,-0.013983,0.135097,-0.005585,-0.06669,0.00674,0.107713,0.031212,0.042676,0.090165,-0.014101,-0.07143,-0.037388,0.054766,0.079207,0.023107,0.036806,0.012333,0.046537,0.002522,0.086603,0.017018,-0.013759,0.07125,0.026219,-0.085893,-0.038737,-0.03836,0.03166,0.075943,-0.077572,-0.007269,0.013243,-0.011998,0.002616,0.047245,0.075794,0.031333,-0.057257,-0.02806,-0.043687,0.020406,0.010672,-0.024869,-0.048201,0.010618,-0.015682,-0.01145,-0.04854,-0.046376,0.006467,0.003532,-0.004629,0.023067,-0.028231,-0.063754,-0.049999,0.009982,-0.008101,-0.00977,-0.03571,0.0957,-0.005905,-0.015795,-0.001552,-0.024984,-0.000253,-0.010519,0.073556,-0.069766,0.084704,0.066584,-0.034618,0.061455,-0.047153,0.083026,-0.000575,-0.050955,0.032935,0.021679,-0.070974,-0.013435,-0.123614,0.015068,0.018971,0.0,0.109476,0.015474,-0.022919,-0.020237,0.002376,-0.041577,0.0014,-0.054416,-0.032835,0.002829,-0.043756,-0.093348,0.049906,-0.041392,-0.042513,-0.072652,0.044688,0.045928,0.080693,0.023731,0.005375,-0.050682,0.003904,-0.068538,0.00633,0.111791,0.023945,-0.005958,0.027151,-0.000261,0.097445,-0.111111,0.008261,-0.005633,0.033685,-0.047443,0.029482,-0.024084,-0.054792,-0.029682,0.050569,-0.001858,-0.10075,0.019153,0.041801,0.020916,-0.002695,0.021845,0.041117,0.018925,-0.090849,0.007636,-0.035238,-0.034729,-0.00811,-0.062192,0.008724,0.041468,-0.028306,-0.002815,0.084479,-0.003987,0.038296,-0.014772,0.019195,0.024522,0.080783,-0.052414,-0.043902,-0.004435,-0.058686,0.019117,0.041301,0.092187,-0.080037,-0.032999,-0.034539,0.012635,-0.017809,-0.001175,-0.025612,0.01538,0.048762,0.038775,0.069758,0.017989,0.005364,0.062135,0.041256,0.028142,0.00123,0.086872,0.049331,0.040774,-0.025803,-0.0,-0.069638,-0.0439,0.008039,-0.085737,-0.088443,-0.033886,0.02761,0.019132,0.078896,0.008268,0.0273,-0.01893,-0.042316,-0.137504,0.047684,-0.005885,-0.039555,0.102748,-0.065191,0.015381,0.01777,0.073871,0.065595,-0.045808,-0.01264,0.029126,0.037278,0.096959,0.01569,-0.008287,0.063903,-0.027928,-0.084429,0.083964,-0.013995,0.004617,0.053562,-0.061049,-0.017619,-0.000289,-0.025473,0.088672,-0.028443,-0.030855,-0.084282,-0.042318,-0.008992,-0.097774,-0.027571,-0.075791,-0.046535,-0.052024,0.104703,0.026228,0.021363,0.002876,0.093491,0.05922,-0.029634,-0.027061,0.087224,0.054513,0.054052,0.088009,0.066229,0.024994,0.040983,-0.078848,0.022981,-0.026505,-0.039738,-0.030045,0.031455,0.12203,0.075281,-0.089606,-0.146338,0.040612,0.045352,-0.013252,-0.009384,-0.01092,-0.12297,0.066221,0.017811,-0.026284,0.029796,0.117738,0.081593,-0.060507,-0.028848,-0.0398,-0.059478,0.012347,-0.030816,-0.0,0.059994,-0.006928,0.002792,0.010503,0.082652,0.005715,-0.018886,-0.060741,-0.041917,-0.163113,-0.061309,0.084447,0.004831,-0.016856,0.047361,-0.112856,-0.04671,-0.058178,0.027194,-0.023467,0.040544,-0.008532,0.010615,-0.031083,0.016065,-0.056027,0.032381,0.042089,0.014102,-0.032527,-0.037718,0.019141,-0.068503,-0.022128,-0.021007,0.068772,-0.016805,0.061004,0.028851,0.040734,-0.017172,-0.084035,-0.033652,-0.043862,-0.004546,-0.014045,0.009476,0.024414,-0.005388,-0.017479,-0.003848,-0.037513,0.022812,-0.04692,-0.040606,-0.04559,-0.043155,-0.001888,-0.015305,0.061716,0.057912,-0.013681,-0.057881,-0.08809],"category":"OTP Phishing","source":"seed_minilm"},{"embedding":[-0.042565,-0.025228,-0.063215,-0.006369,0.034541,-0.070944,-0.032914,-0.112529,-0.012402,0.007899,0.035055,0.000608,-0.033798,0.052656,-0.020225,0.077104,-0.071281,-0.028272,0.02354,0.054443,-0.042932,-0.025942,-0.018314,0.056414,-0.020316,-0.113203,0.053227,0.047538,-0.06323,-0.002977,-0.041615,0.106449,0.059984,-0.063355,0.044692,0.021416,0.010808,-0.026117,0.083196,-0.11918,0.051191,-0.032816,-0.071146,-0.000994,0.092737,0.029327,0.016879,-0.008946,0.06398,0.01842,0.026735,0.034082,-0.018031,-0.052519,-0.046751,0.033853,0.014385,0.01239,0.073693,-0.012246,0.017112,-0.032843,0.097765,0.029108,0.019732,0.007098,-0.011796,-0.097626,-0.054984,-0.022205,0.082136,-0.005715,-0.03647,0.001119,0.045693,0.039374,-0.007846,0.005512,0.071464,0.004553,-0.016629,-0.019026,0.032146,0.039162,0.012599,0.044964,-0.01868,-0.002073,-0.015967,-0.070529,-0.071103,-0.006271,0.053072,0.027492,0.033201,-0.049836,0.008959,0.032105,-0.115082,0.018572,-0.016601,0.016576,-0.019424,0.067981,-0.007163,0.013988,0.026887,0.018207,-0.047715,-0.006796,0.026187,0.029521,0.058456,0.009924,-0.061202,0.14087,-0.063913,0.083564,0.003565,0.011861,-0.013792,-0.050722,-0.092663,-0.015113,-0.135679,-0.029045,0.012767,0.0,0.000612,0.027365,-0.03044,0.032498,0.019187,-0.044158,-0.039315,-0.069686,-0.050853,-0.024819,-0.022053,-0.052447,-0.026816,0.066715,-0.011149,-0.088194,0.056308,0.072684,0.083319,0.024948,0.01227,-0.063959,-0.025107,-0.0715,0.066734,0.09946,0.014395,-0.009701,0.040424,-0.016337,0.105035,-0.046367,0.012377,-0.00044,-0.042918,-0.016551,-0.011464,0.02134,-0.09062,0.028095,0.040203,0.065053,-0.108776,-0.011281,0.017141,-0.011872,0.002659,-0.050757,0.033559,0.039359,-0.125859,-0.023679,-0.019464,-0.061372,-0.03332,-0.105692,-0.013669,0.013226,-0.03134,-0.114399,0.016657,-0.021882,-0.010286,0.053857,-0.01026,0.073455,-0.021707,-0.063836,0.020537,0.055587,-0.056469,0.039729,-0.047661,0.072054,-0.089734,-0.033713,-0.056565,-0.028465,-0.030539,0.021889,0.040378,-0.012844,-0.063607,0.034149,0.097197,-0.029706,-0.029542,0.02228,-0.070924,0.000147,0.080603,0.031757,0.042019,-0.015406,-0.048487,-0.0,-0.063389,-0.020515,0.006146,-0.049454,-0.048089,-0.004205,0.015671,0.026638,0.059161,-0.026254,0.054879,0.004276,0.027057,0.000572,0.068375,0.087475,-0.078007,0.119485,-0.011553,0.000706,0.031251,0.055912,-0.031897,-0.079345,-0.075656,0.078253,0.023894,0.07702,-0.004691,-0.03004,0.044429,-0.00622,-0.133317,0.132744,0.024936,0.032668,0.034529,-0.010297,-0.023807,-0.011986,-0.005236,0.075783,-0.002477,0.053139,-0.005924,-0.021682,0.04599,0.002,0.00042,-0.027663,-0.015962,-0.026482,0.101635,-0.07328,0.012021,-0.034804,0.110363,0.054432,-0.032221,-0.07888,0.050595,0.002744,-0.02843,0.077302,-0.005643,-0.006386,-0.038551,0.006621,0.00131,0.001852,-0.061947,0.041148,0.003908,0.01197,-0.009114,-0.050197,-0.086337,0.002871,0.040418,-0.02078,-0.058087,-0.028578,-0.043594,0.057727,0.068092,-0.003423,0.044658,0.07242,0.041311,0.001219,-0.010085,0.037535,-0.052671,0.041006,-0.04903,-0.0,0.073219,-0.031637,-0.101597,0.001311,0.194873,0.020863,-0.092599,-0.031037,-0.026783,-0.164671,-0.04938,0.049876,0.001595,0.017827,0.087969,-0.089046,-0.059342,0.002326,0.031861,-0.048358,-0.012322,0.022299,-0.013997,0.011266,0.01803,-0.026763,0.133287,-0.005688,-0.042106,-0.004222,-0.020292,-0.016183,0.006365,-0.016936,0.016025,0.043176,-0.004841,0.064569,0.025547,-0.025766,0.008913,-0.029436,-0.018332,-0.048029,-0.049997,0.056912,0.012179,0.043412,0.001675,-0.025048,-0.081668,-0.048907,0.026883,-0.016912,0.027953,0.023782,-0.059152,0.048891,0.038808,0.01349,0.079863,-0.021974,-0.051976,-0.077163],"category":"OTP Phishing","source":"seed_minilm"},{"embedding":[-0.079714,0.0815,0.078599,-0.009045,-0.00592,-0.057749,0.039006,-0.032887,-0.02394,0.005277,0.053491,0.03126,0.013028,-0.023935,-0.086171,0.006662,0.021214,-0.045449,0.059673,0.071856,-0.062808,0.012339,-0.004702,-0.020708,0.101961,-0.0512,-0.028724,0.065384,-0.020919,0.012053,0.025646,0.077908,0.01494,-0.076492,-0.054305,0.03747,-0.047709,-0.048461,-0.009268,0.00668,0.003471,0.069236,-0.037754,0.027236,0.08081,0.029991,-0.011469,0.085703,0.001245,0.043876,0.051702,-0.010533,-0.069802,0.042208,-0.132084,0.027266,0.042203,0.035556,0.007546,-0.036692,0.058302,-0.001017,-0.030085,-0.004321,0.075689,0.039061,-0.033174,0.030098,0.038718,0.024622,0.098728,-0.011265,0.012219,0.019734,-0.053871,0.082647,-0.007105,0.025225,-0.068691,0.022746,-0.013721,-0.016294,-0.023375,-0.04053,0.001259,-0.010928,-0.004591,0.075509,-0.016203,-0.045334,0.066276,0.097452,0.006663,-0.013131,-0.0318,0.026692,-0.031731,0.006308,-0.094698,-0.013328,0.084425,0.095926,-0.058834,-0.058291,0.050915,-0.015449,0.119697,0.025623,-0.007064,-0.02997,-0.011068,0.015323,0.061524,0.016066,-0.049991,0.045255,-0.07466,0.05305,0.023009,-0.007395,-0.014663,0.054633,-0.07805,-0.091384,-0.003093,-0.048468,0.075178,0.0,-0.033776,0.082445,-0.043215,-0.029529,0.059886,-0.046707,0.067282,-0.002395,-0.043164,-0.02244,0.009522,0.004245,0.041622,-0.005344,-0.204879,-0.115526,-0.008574,0.057962,0.053294,-0.003129,-0.036084,0.028038,-0.030235,-0.046309,-0.036247,0.079664,-0.013502,-0.011114,0.04721,0.002799,0.065776,-0.003361,-0.022573,0.040765,0.00105,0.026836,0.09706,-0.06172,0.0012,-0.042677,-0.030529,-0.025166,-0.089178,-0.001582,-0.065903,-0.054103,-0.034751,0.048462,0.051901,-0.0369,-0.039849,-0.015749,-0.072243,-0.092529,-0.034099,-0.062679,-0.022397,-0.022394,-0.016528,-0.00638,0.128722,0.018157,-0.048837,-0.032483,-0.134153,-0.024491,-0.024044,-0.117696,0.033034,-0.004589,0.002168,0.042312,0.109415,0.053163,-0.002859,0.030827,0.001218,0.011338,-0.004783,0.029032,-0.047161,-0.069857,0.03957,-0.004579,0.052544,0.056936,-0.001701,-0.034384,-0.017918,0.067537,0.01381,0.069619,0.0505,0.03887,0.098544,-0.0,-0.063504,-0.014189,-0.076034,-0.010336,-0.027944,0.001435,-0.008386,0.064035,0.03531,0.065099,0.034192,-0.006183,0.057611,-0.029359,0.012393,-0.033249,0.087604,-0.017974,-0.027416,-0.007646,-0.008024,0.046585,0.079041,0.102187,0.034607,0.122849,-0.011157,-0.013307,0.031765,-0.011054,0.062537,-0.046523,-0.015587,0.086798,0.080909,0.00463,-0.00805,0.031864,0.011817,0.009857,0.035445,0.018983,-0.017753,0.024845,-0.0094,-0.130634,0.032433,-0.080781,0.048608,-0.052411,0.101375,-0.006634,0.044894,0.020281,-0.000225,0.147943,0.061536,-0.06198,0.041562,-0.042223,0.048096,-0.010613,-0.020317,-0.031727,0.012963,0.069943,0.049793,-0.034227,0.095591,0.031338,-0.041234,0.024794,0.020693,-0.073896,0.082916,0.123126,-0.029584,0.01204,-0.032009,-0.037753,0.048481,-0.000899,0.049318,0.05554,-0.038458,-0.081381,-0.102263,0.02004,0.004012,0.009946,-0.044809,-0.110298,-0.014773,0.078017,0.060348,-0.0,-0.036427,-0.005446,0.056388,-0.003851,0.000295,-0.022365,0.014277,-0.040557,-0.029324,-0.010309,-0.052502,0.000631,-0.076958,-0.004299,0.009083,-0.106744,-0.01838,0.012111,-0.044223,-0.035943,0.020375,0.006311,-0.023093,-0.041925,-0.021556,0.044721,-0.023343,0.100064,0.066994,-0.078786,-0.021043,-0.022335,-0.061943,-0.008447,-0.091087,-0.006829,0.028347,0.021943,-0.00974,0.061301,-0.01339,-0.028874,-0.007601,0.018951,0.002312,-0.037707,-0.005879,-0.00368,-0.039121,-0.041285,0.048534,-0.105002,0.02301,-0.023069,-0.038982,-0.099021,-0.026127,-0.007899,-0.102514,-0.033349,-0.015045,-0.024939,-0.022155,-0.007832],"category":"OTP Phishing","source":"seed_minilm"},{"embedding":[-0.044125,0.015984,0.02086,-0.02133,-0.045643,0.033413,0.097551,0.009927,-0.0382,0.031525,-0.038749,-0.074862,0.062643,-0.049387,-0.046655,0.015578,0.005533,-0.072551,-0.047599,-0.006049,0.002039,-0.036021,-0.081847,-0.000253,0.096227,0.009881,0.022844,0.086103,-0.006865,-0.002227,0.016651,0.04513,-0.050096,-0.045914,0.047414,0.010335,-0.061171,-0.088006,-0.000618,-0.031604,0.007101,-0.043196,-0.088595,0.031908,0.038128,0.058193,-0.02927,0.020192,0.006335,0.066039,-0.042231,0.019045,0.020695,-0.023851,-0.093904,-0.013848,-0.001882,0.031167,0.023593,-0.03808,-0.020914,0.042242,-0.059418,-0.016209,-0.023003,0.032464,-0.015256,-0.002113,0.070463,-0.057665,0.134862,-0.048107,0.049617,0.023257,0.017849,-0.013182,-0.073409,-0.025657,0.023963,0.002998,-0.053211,-0.025477,-0.063161,-0.030038,-0.01314,-0.035829,0.007917,0.040783,0.013287,-0.019,0.097435,0.02964,0.031351,0.007854,-0.043958,-0.0422,-0.0177,0.016259,-0.02783,0.040892,-0.017099,0.072917,-0.06052,-0.036785,0.057877,-0.026209,-0.028744,-0.005023,0.048756,-0.095991,-0.028104,0.028987,0.014313,0.053493,-0.048731,0.071712,-0.044227,0.040772,0.027849,-0.049029,0.026886,0.029376,-0.084596,-0.022079,-0.047854,-0.106991,0.035282,-0.0,0.034556,-0.004951,0.123115,0.046717,-0.086169,-0.059994,0.011109,0.001029,-0.047365,-0.011779,-0.019621,0.019734,0.053515,-0.058981,-0.093505,0.030524,-0.076201,0.015267,0.021042,0.157209,0.046181,-0.030551,0.029138,-0.05556,0.024296,0.014203,-0.044049,-0.036723,0.048052,0.055067,0.033574,0.019365,0.00325,-0.014277,-0.028906,-0.014036,0.034073,-0.075715,-0.063874,0.006203,-0.060972,-0.02469,-0.031494,-0.024825,-0.04322,0.029721,0.049658,0.038562,0.060323,0.026079,-0.073411,-0.013789,-0.012255,0.070352,0.045757,-0.052723,0.035683,-0.012133,0.000502,0.033535,0.071471,-0.043456,-0.037039,0.005426,-0.001919,-0.097781,-0.007799,-0.042086,0.025648,-0.094972,0.059909,0.014545,0.028853,0.01895,-0.023224,-0.041082,-0.000926,0.039725,-0.025027,0.054004,0.078505,0.018022,-0.028598,-0.098046,0.111156,0.140293,-0.020084,-0.110005,-0.01931,-0.062325,-0.034067,-0.013732,0.050451,0.014712,-0.060337,-0.0,-0.024752,-0.001237,0.001233,0.04254,0.005632,0.036918,0.042978,0.0741,0.018024,0.14808,0.097921,0.043314,0.094593,-0.041265,-0.025898,-0.069767,0.03627,0.043777,-0.05746,-0.026312,0.004254,0.041024,0.010771,0.068517,-0.032761,0.013888,-0.010824,0.081263,0.007485,-0.036064,-0.005496,-0.006548,-0.106,-0.02388,0.036588,-0.10769,0.126894,-0.085376,0.017264,-0.003754,-0.096379,-0.030799,-0.007217,0.002915,-0.027106,-0.095741,0.068959,-0.054307,0.083098,-0.071856,0.090857,0.0107,-0.005948,0.055261,0.014475,0.017829,0.025679,0.004817,0.077682,-0.012526,-0.015638,0.069978,0.062254,0.078525,0.06765,-0.03473,0.074329,-0.005797,0.089996,-0.07267,-0.036838,0.022442,-0.030703,0.015959,0.030742,-0.023498,0.04353,0.087028,0.042476,0.018647,0.074009,0.012202,0.052584,-0.053145,0.056748,0.025707,0.049612,-0.102754,0.013136,0.039362,-0.026763,-0.001431,0.024722,0.077003,0.092347,-0.0,0.059425,0.026255,-0.017259,0.019657,-0.015648,-0.027378,-0.019634,0.036144,-0.087301,-0.06983,0.016458,-0.003611,-0.082911,-0.036651,0.010966,-0.11244,-0.01281,0.074982,0.008317,-0.026413,0.081466,-0.000461,0.037687,-0.041646,-0.071423,0.011974,0.075782,0.105334,0.016743,-0.072042,-0.03726,-0.048286,-0.044934,-0.056565,-0.027165,0.014667,-0.003236,0.066179,0.004669,0.034825,-0.037107,-0.087594,0.000548,0.022179,-0.05203,0.039212,-0.063921,0.000778,0.046061,-0.05934,0.025693,-0.048652,0.003709,-0.006266,-0.008895,0.032391,-0.062654,-0.067731,0.005334,0.044618,0.050483,-0.044637,-0.16142,0.062118],"category":"Lottery Scam","source":"seed_minilm"},{"embedding":[-0.038895,0.041086,0.009084,0.019895,0.022604,0.003853,0.142317,0.020438,-0.076671,0.011105,-0.010588,-0.126239,0.025561,0.023851,-0.03442,0.062809,0.039852,-0.059951,-0.005672,-0.01386,0.022756,0.016435,-0.030662,-0.021525,0.036809,-0.058038,0.018185,0.063322,-0.025831,0.00237,0.035551,0.068082,-0.015067,-0.015128,-0.005854,0.050152,-0.011313,-0.064641,-0.028637,-0.0432,0.023636,-0.06469,0.005462,-0.045385,0.045242,0.027202,-0.018743,0.031532,-0.034032,-0.02744,-0.058465,0.000786,-0.009544,-0.023369,-0.047991,-0.053906,-0.013833,0.034861,-0.058798,-0.102363,0.002093,0.001478,-0.08919,0.05738,0.017647,0.017067,-0.027678,-0.064896,0.033904,-0.078174,0.103738,-0.024183,0.051844,-0.006255,0.005891,-0.005193,-0.007597,0.014706,0.073828,0.051033,-0.035938,-0.037435,-0.038768,-0.030001,0.003399,-0.023562,0.008277,0.031871,0.002782,0.00931,0.083753,0.002795,0.036953,0.027425,-0.024125,-0.052969,-0.005075,0.005167,-0.032543,0.064736,-0.013072,-0.010061,-0.092971,-0.008365,-0.020191,-0.00375,-0.030803,-0.034894,0.063261,-0.075304,-0.053116,0.030495,0.073593,0.024721,-0.015949,0.053281,-0.08547,0.074466,0.04487,-0.081311,0.001243,0.066099,-0.123155,-0.098192,-0.052018,-0.123435,0.019274,-0.0,-0.014469,-0.007098,0.089454,0.030695,-0.03489,-0.03244,-0.034439,0.022758,-0.027422,-0.005224,0.023881,0.004521,0.101571,-0.030821,-0.047224,0.072085,-0.048896,0.022523,0.052488,0.059701,0.064901,5.8e-05,0.054535,-0.036197,0.090017,-0.045742,0.003466,-0.080283,0.022765,0.037989,0.04123,0.023457,-0.033194,-0.075077,0.018846,0.020388,0.04908,-0.050421,-0.037626,-0.021937,-0.039134,0.009804,-0.008601,0.043207,-0.049378,0.053023,0.045228,0.020546,0.015926,0.091159,-0.040557,0.022222,-0.082433,-0.039146,0.037775,-0.05316,-0.053319,0.054002,0.030437,-0.015373,0.050542,-0.06945,-0.061005,-0.00255,-0.049279,-0.017258,0.040887,-0.042253,0.100755,-0.029047,0.022526,-0.006136,0.040193,0.031236,-0.061059,-0.036563,0.031694,0.037792,0.039347,-0.003312,-0.024352,0.066631,-0.01749,-0.120674,0.126785,0.0779,0.014769,-0.11503,0.054853,-0.047196,-0.02768,-0.049109,0.067919,0.011836,-0.029212,0.0,-0.031676,0.013842,-0.032362,0.00367,0.037834,0.053393,0.021147,0.009272,0.035067,0.159789,0.074223,0.009107,0.118647,-0.00526,0.000507,-0.01445,-0.023781,-0.004674,-0.115738,-0.01555,-0.005701,0.120955,0.014627,-0.021519,0.025131,0.049169,-0.015678,-0.024852,0.03386,-0.074915,0.05169,0.006369,-0.232473,-0.01935,-0.005351,-0.016684,0.125578,-0.132045,0.016724,0.070899,-0.020763,0.009226,-0.000291,0.073629,-0.01753,-0.154533,0.00931,-0.045826,0.07206,-0.062789,-0.007035,-0.03864,0.021631,0.005056,0.047993,0.057664,-0.008632,0.026221,0.072867,0.015824,0.016108,0.039015,0.007757,0.037927,0.049332,-0.037909,0.021378,0.044984,0.098217,-0.058243,0.03727,0.022344,0.032687,-0.02226,-0.019291,0.036859,0.028926,0.103255,-0.006171,0.022931,0.05317,0.026896,0.02877,-0.046374,0.042905,-0.053187,0.074831,-0.091067,0.0219,0.034591,0.004594,-0.036441,0.089696,0.03337,0.102552,-0.0,0.047046,0.014808,-0.060279,0.050653,-0.063639,-0.002948,-0.069279,0.033399,-0.086372,-0.038304,0.04168,-0.015319,-0.056506,0.01909,-0.0009,-0.092826,-0.055413,0.062562,-0.020102,-0.086113,0.097128,-0.008927,-0.040955,-0.017581,-0.054283,0.037446,0.042456,0.009262,-0.040094,-0.001277,-0.080661,0.01565,-0.037137,-0.058284,0.046107,-0.012007,0.035007,0.005015,0.004036,-0.014426,0.007103,-0.041218,0.024298,0.054026,-0.062858,0.019548,-0.039486,-0.013211,0.01773,0.012281,-0.012585,-0.080204,0.020024,-0.001646,-0.001815,0.006296,-0.03466,-0.032061,-0.01688,-0.009226,0.048152,-0.096363,-0.081986,0.010413],"category":"Lottery Scam","source":"seed_minilm"},{"embedding":[-0.052242,0.064104,-0.034894,-0.04777,-0.058823,-0.031568,0.053668,0.01884,0.008927,-0.010677,0.011512,-0.022482,0.016094,0.001369,-0.001681,0.040353,-0.011053,-0.09718,-0.028777,0.00523,0.034575,0.023557,-0.044412,-0.065093,0.09633,-0.094879,0.019405,0.072614,0.025614,0.027368,0.096914,0.109239,-0.034982,-0.027336,-0.035197,-0.031662,-0.139236,-0.014779,-0.00788,-0.024279,0.007587,-0.038712,0.002108,0.020097,0.045605,0.020287,0.003034,0.10788,0.002255,0.133408,0.032717,0.022981,-0.04418,0.006849,-0.054444,-0.031971,-0.054982,0.023616,-0.031872,0.045796,0.030464,0.102225,-0.04342,-0.019413,-0.014989,-0.045334,-0.057513,0.016308,0.018839,-0.00413,0.152576,-0.062456,0.028818,0.031454,-0.009437,0.086935,-0.063263,-0.035483,0.006666,0.0424,-0.07041,-0.045395,0.003484,-0.007301,0.050531,-0.016974,0.030273,0.073759,-0.08168,-0.045533,0.062201,0.083456,-0.02052,0.024557,-0.052283,-0.001906,-0.021677,0.015048,-0.086941,0.033046,-0.000285,0.107819,-0.079988,0.076443,-0.001792,-0.011565,0.048479,-0.021479,0.048718,-0.058331,-0.037915,-0.00569,0.022023,-0.003731,-0.049857,0.017233,-0.108487,0.067137,0.039654,-0.038206,-0.035921,0.038473,-0.017666,0.005193,-0.058324,-0.096792,0.048428,0.0,-0.027047,0.01394,0.048704,0.006823,-0.049619,-0.061059,-0.019988,-0.019289,0.050536,0.021624,-0.017481,-0.064709,0.09834,-0.067882,-0.017378,-0.001193,0.028821,-0.089018,0.089337,0.071843,0.001736,-0.026253,0.012993,-0.00824,0.042542,0.054712,0.076939,-0.024167,-0.021774,0.01488,0.057775,0.014378,-0.062747,0.00168,-0.03061,0.024066,0.051925,-0.069966,-0.076288,-0.011043,-0.022451,-0.019867,-0.02086,0.002349,-0.048664,0.05134,0.065413,0.04911,0.080238,0.055268,-0.082003,0.015795,-0.011545,0.003407,0.047253,-0.072117,0.016356,-0.008896,-0.00198,-0.023382,-0.002839,-0.139581,-0.019197,0.004262,-0.130802,0.002388,0.026467,-0.142175,0.037537,-0.005103,0.011882,0.032431,0.043541,-0.039281,-0.061513,0.070614,0.025531,0.020374,-0.006223,0.069974,0.009862,0.062976,0.045344,-0.054962,0.10941,0.073995,0.011863,-0.062377,0.016566,0.022975,0.018768,0.010387,0.037567,0.017315,0.015631,-0.0,-0.09942,0.020436,-0.032889,-0.023027,0.032928,-0.036054,0.051794,0.117635,-0.030584,0.132271,0.040103,0.075683,0.039534,-0.031346,-0.007505,-0.068242,0.020911,0.041367,-0.01252,0.025082,-0.002434,0.119262,0.046256,-0.014287,-0.003085,0.012998,0.018433,-0.010205,0.032551,-0.057341,0.024144,-0.014616,-0.094659,0.015718,0.047644,-0.017298,0.141794,-0.035314,-0.046492,0.033548,-0.015287,0.034226,-0.046957,-0.018646,-0.030661,-0.061566,0.037129,-0.017948,-0.000945,-0.073381,0.173859,0.019534,0.010299,0.066191,0.077422,0.048953,0.059647,-0.024053,0.038145,-0.052297,0.030285,-0.007486,0.020428,0.008311,-0.002154,-0.005996,0.076627,0.028006,0.054955,0.014415,-0.06042,0.019834,-0.053222,0.030441,0.073222,0.014629,0.002685,0.074704,0.031738,-0.00526,0.008125,-0.009351,0.058761,0.016063,0.009306,-0.009998,0.039565,-0.079925,-0.03314,0.054122,-0.058991,-0.028071,-0.004243,0.045558,-0.009865,-0.0,-0.026399,-0.016512,0.044631,-0.075322,-0.002877,0.022543,-0.051923,0.038284,0.005455,-0.045023,-0.010818,-0.042161,-0.067716,-0.00519,-0.040717,-0.073093,0.024497,0.008207,0.008347,-0.016144,0.048434,0.044428,0.000608,-0.055262,-0.060147,0.020104,-0.020638,0.09001,0.010912,-0.029493,-0.026554,-0.025363,0.053058,-0.118966,-0.115783,0.010231,0.040366,-0.01967,0.054065,0.01897,-0.013863,-0.077726,0.019368,0.031192,-0.013974,-0.030631,0.008059,-0.079755,-0.017844,-0.083779,-0.026023,-0.040762,0.022709,-0.066758,-0.040702,-0.109596,-0.053738,-0.050639,0.001593,0.047589,0.069271,-0.019148,-0.14912,-0.016623],"category":"Lottery Scam","source":"seed_minilm"},{"embedding":[-0.161047,0.090035,0.011616,-0.05308,-0.036761,-0.024501,0.109203,0.07739,-0.042544,-0.030463,-0.003345,-0.07734,-0.005722,0.047799,0.036531,0.022564,0.130484,-0.042803,-0.008275,-0.06028,0.010252,-0.048184,-0.016208,-0.039574,0.075538,-0.007196,0.018334,0.036957,-0.02966,0.026289,0.025015,0.112654,-0.011187,-0.049312,0.031614,0.015129,-0.036969,-0.082072,0.013519,-0.020871,-0.012858,-0.022595,-0.022246,-0.055793,0.116373,-0.064464,0.014799,0.043354,0.11283,-0.032672,-0.059672,-0.031969,0.071663,-0.009456,-0.008516,0.00297,0.081239,0.034341,-0.060377,-0.017021,-0.040828,-0.046712,-0.015839,0.013554,-0.043197,-0.074557,0.014844,0.015133,0.001276,0.03473,0.146681,0.018699,0.058045,-0.003002,0.030438,0.080758,-0.017893,0.056558,0.056169,-0.043926,-0.110422,-0.074959,0.036229,-0.080445,-0.028994,0.076912,0.032228,0.044997,-0.011855,0.020463,-0.006164,-0.03417,0.014623,-0.013852,-0.104964,0.019619,-0.029486,-0.007297,0.030521,0.066561,0.010741,0.060658,-0.048314,-0.015375,0.135711,0.073399,-0.030344,-0.013503,0.042349,-0.051637,-0.056599,0.027696,0.076094,0.038066,-0.06078,0.012275,-0.065249,0.039243,0.133346,-0.023447,0.094208,0.032509,-0.056662,-0.043843,-0.056704,-0.05401,-0.029131,-0.0,0.064849,-0.014509,0.037931,-0.026919,-0.019472,-0.038019,-0.023265,-0.002513,-0.071487,0.026107,-0.027762,-0.04603,0.066246,0.007345,-0.021297,-0.029026,-0.129681,-0.059809,0.063983,0.013248,0.028312,-0.098124,0.000235,0.007364,0.007203,0.056456,0.002715,-0.015402,-0.005196,0.045431,0.00861,0.029763,0.054357,-0.051938,-0.048828,0.024301,0.077746,-0.067997,-0.033969,0.01832,0.005932,-0.031585,-0.090042,0.069807,-0.070834,0.006709,0.017453,-0.034551,0.116286,0.027547,-0.0512,-0.02208,0.033108,-0.008243,-0.022276,-0.061501,0.00333,-0.094817,0.028583,-0.006135,-0.008148,-0.062997,-0.028524,0.021778,-0.11853,0.093482,0.062508,-0.024498,0.020633,0.034066,0.062383,0.034851,-0.003787,-0.033833,-0.02996,-0.048004,0.096874,0.009867,0.061344,0.062122,-7.8e-05,0.01354,0.038534,-0.039856,0.084807,0.070485,0.007303,-0.125936,-0.010152,-0.021536,0.015304,-0.007588,0.030985,0.036701,-0.062554,0.0,-0.042312,0.121521,-0.011783,-0.002692,0.016154,-0.027064,0.001671,0.081847,0.002527,0.087043,-0.05456,0.017457,0.066482,-0.016232,0.024463,0.0065,-0.017083,-0.035608,-0.075649,0.043401,0.058078,0.019056,0.003232,0.044714,0.060603,0.006015,-0.055585,-0.069476,-0.000716,-0.014137,0.044515,-0.107018,-0.127499,-0.057511,0.08568,-0.003398,0.068123,-0.086972,0.034457,-0.005159,-0.005193,-0.005848,-0.005898,0.085805,-0.01268,-0.019512,-0.012634,0.032939,0.054412,0.008835,0.021933,0.007944,0.052532,0.086606,-0.024838,-0.013711,-0.015405,0.046038,-0.015272,0.062651,0.028225,-0.025459,-0.006734,0.115352,0.042828,0.043806,0.045593,-0.001956,-0.026674,-0.05925,-0.02146,0.032545,-0.033571,-0.026287,-0.017266,0.02128,-0.07267,0.042296,0.019596,0.038799,0.034848,0.057492,-0.008745,-0.047371,0.002265,-0.028161,0.000319,-0.05726,0.016053,0.014078,-0.010881,-0.019443,-0.010369,0.04523,0.080859,-0.0,0.04093,0.011926,-0.022237,-0.02723,0.03683,0.009274,-0.082287,0.057216,-0.000473,-0.016988,0.09305,0.005455,-0.137323,0.028024,-0.08041,-0.09246,0.010921,0.020724,0.022312,-0.073564,0.025669,0.01395,0.003942,-0.113625,-0.072434,0.003234,-0.03554,0.108812,0.017365,-0.051899,-0.036944,-0.009976,0.004537,-0.023783,0.008115,-0.054719,-0.048129,0.055166,0.040547,0.051032,-0.023401,-0.038548,0.014685,0.014055,-0.058629,0.030051,-0.053222,-0.010858,0.000349,-0.066626,0.022496,-0.054873,0.005541,-0.017246,0.015651,-0.037284,0.007625,-0.015702,0.050452,0.022277,0.017078,-0.091085,-0.056796,0.068153],"category":"Lottery Scam","source":"seed_minilm"},{"embedding":[-0.053626,0.113203,-0.022335,-0.020656,0.10056,-0.026149,0.084843,0.048049,0.011741,0.062251,0.072108,-0.060311,0.051298,0.038842,-0.038643,0.099149,0.016736,-0.001109,0.047188,-0.019403,0.063502,0.016458,-0.006203,0.028325,0.059904,0.017638,0.039847,0.044537,-0.06807,-0.006763,0.090295,0.090104,-0.033869,-0.108865,0.037466,0.030587,-0.113087,-0.023727,0.054485,-0.097233,0.02167,0.012702,-0.004626,-0.010703,0.032556,0.036159,0.05264,0.112417,0.01976,0.102401,-0.0077,-0.004618,0.015769,0.039864,-0.064902,-0.098065,-0.022341,0.007809,-0.006943,-0.022386,0.001092,0.053226,-0.048773,-0.019933,0.01733,0.00623,-0.035021,-0.039926,0.025656,-0.053752,0.075301,-0.006639,-0.042109,-0.040968,-0.076102,-0.034944,-0.017508,0.006786,0.021927,-0.016412,-0.047923,0.033584,0.095457,-0.00602,0.04111,0.025839,-0.002544,0.057617,-0.04354,-0.013714,0.047874,0.06039,-0.014132,0.063436,-0.055538,-0.071263,-0.044363,-0.015691,-0.066278,0.076153,0.052918,0.062311,-0.119104,-0.002822,-0.013872,-0.038267,0.08759,0.013734,0.034711,-0.033709,-3.8e-05,0.015207,-0.005224,-0.007147,-0.014361,0.024669,-0.08183,0.081783,0.004741,-0.06069,0.013022,0.00946,-0.03518,-0.062389,-0.008219,-0.10236,0.042732,0.0,0.022146,0.093987,0.086547,-0.000487,0.0075,-0.039936,0.040742,0.023208,0.028839,-0.035468,-0.030255,-0.085218,0.008295,-0.022372,-0.04885,-0.072924,0.044954,-0.020788,0.117716,0.056223,0.012716,-0.021799,0.017051,0.017693,0.030804,0.009239,0.019573,0.015608,0.007886,0.034384,0.017859,0.001115,-0.089982,-0.058974,0.029589,0.01459,0.111036,-0.075023,-0.110598,-0.0587,-0.028861,0.005298,0.026823,0.037644,-0.075092,0.051518,-0.000491,0.071251,0.055428,0.044664,-0.042301,0.019545,-0.032513,-0.049502,-0.04685,-0.004844,-0.067516,-0.018471,0.074008,0.013364,0.082989,-0.126501,-0.071118,-0.069668,-0.092859,0.022626,-0.023489,-0.093882,0.082292,0.040527,-0.006701,0.079336,0.078273,0.042809,-0.102306,0.012719,-0.020797,0.062087,-0.013453,0.037106,-0.029697,-0.00211,-0.01114,-0.061288,0.103506,0.104768,0.002162,-0.015653,0.028403,-0.045196,-0.01916,0.000512,0.059613,0.041447,-0.020704,-0.0,-0.04816,0.000291,-0.002156,-0.002887,0.019702,-0.031032,0.011707,0.102406,0.042689,0.063493,-0.064327,-0.01162,0.072524,0.010862,-0.022613,-0.035492,-0.027722,0.052399,-0.03154,-0.028896,0.017531,0.081527,0.062737,-0.063582,-0.003275,0.005597,-0.021455,0.023427,-0.008577,-0.01704,0.065519,-0.011068,-0.10155,-0.030668,-0.015925,-0.039321,0.044344,0.028353,-0.024688,0.039081,0.017454,0.000487,0.015446,0.042813,-0.013505,-0.061496,0.006522,-0.079252,0.102766,-0.035122,0.037179,-0.06316,0.025999,-0.030948,0.054073,0.023938,0.025123,0.044681,0.038254,-0.064945,0.024895,0.030241,-0.043858,0.034591,0.068556,-0.048272,0.085886,-0.047591,0.078546,0.004174,-0.018962,-0.047647,0.009387,0.017388,0.073435,0.009499,0.010581,0.055025,0.018097,0.051667,0.090955,-0.050128,0.030178,-0.061259,-0.006806,-0.100349,0.041959,-0.082709,-0.028766,0.065649,-0.077032,0.007066,0.071805,0.068892,-0.003614,-0.0,-0.022065,-0.04043,0.007969,-0.011536,0.028799,0.025937,-0.041759,-0.004262,-0.009248,-0.079573,0.002444,-0.049899,-0.08502,-0.017976,-0.070839,-0.081321,-0.022735,-0.021515,-0.006195,-0.125385,0.009163,0.009894,0.035095,-0.076149,-0.022754,-0.018783,0.035269,0.011439,-0.038459,-0.026263,-0.125015,0.021248,0.07178,-0.120938,-0.063218,0.060403,0.002078,0.021577,0.056557,-0.042412,-0.04693,-0.067535,0.043545,-0.039698,0.014096,-0.047773,0.012407,-0.057349,-0.059213,-0.050134,-0.014804,-0.0418,0.067213,0.06316,-0.036758,-0.014117,-0.036203,-0.048134,0.036491,0.001518,0.107295,-0.025516,-0.082089,-0.027437],"category":"Lottery Scam","source":"seed_minilm"},{"embedding":[0.010276,-0.010989,0.000905,-0.038998,-0.02038,-0.011143,0.120245,-0.026531,-0.037419,-0.030482,-0.075314,-0.064815,0.034084,-0.035452,-0.042628,0.099603,0.02043,-0.066978,-0.071606,0.041272,0.004786,-0.07738,-0.054867,0.004027,-0.006176,-0.03236,0.024439,0.057075,-0.078835,0.00621,0.072124,0.045939,-0.057279,0.010357,0.056738,0.054665,-0.060914,0.018571,-0.053664,-0.091936,-0.016824,-0.092883,-0.009485,0.042892,0.087466,0.116672,-0.012187,0.079666,-0.0018,-0.011206,-0.054317,-0.076988,0.034969,-0.038239,-0.037795,-0.017203,0.00164,0.020178,0.005836,-0.127619,-0.021124,0.036806,-0.021869,-0.013897,0.010449,-0.040399,-0.000555,0.026551,0.009138,-0.081434,0.07378,-0.094309,0.002918,0.011276,-0.001679,0.076316,-0.008732,0.035033,0.057895,0.105714,-0.079842,-0.02228,-0.034641,-0.018403,0.047915,0.01787,-0.008344,0.047115,-0.038113,-0.015439,0.036063,0.018855,0.018931,0.085266,-0.003608,0.030809,-0.013127,-0.069504,-0.018364,0.056497,0.036146,0.053086,-0.019386,0.06743,0.021856,0.008443,-0.017419,0.055945,0.073625,-0.161542,-0.041182,0.024878,0.033687,0.062054,0.000503,0.042512,-0.134946,0.072257,0.049854,-0.013114,0.036994,0.074498,-0.060495,-0.069941,-0.065057,-0.051117,0.056287,0.0,0.00906,0.030252,0.078626,0.021264,-0.055596,-0.014531,0.001774,0.068499,-0.031944,-0.02226,-0.077064,0.002612,0.069797,0.033695,-0.100373,0.034322,-0.005458,0.028873,0.105053,0.067871,0.047449,0.02401,0.04385,-0.046591,0.025821,0.005206,-0.017333,-0.103118,0.112204,0.035467,0.025113,-0.020825,-0.025889,-0.007657,-0.02445,0.022987,-0.023522,-0.055187,-0.020871,0.034717,-0.085323,-0.021759,0.015481,0.032862,-0.065158,0.08555,0.057965,0.010598,0.085896,-0.007809,-0.012879,-0.046683,-0.080656,0.01602,0.028421,-0.079214,0.054891,0.019829,0.006163,-0.074018,0.003276,-0.013829,-0.000141,0.006681,-0.028529,-0.103443,0.052863,-0.059443,-0.025651,-0.053679,0.034123,0.027285,0.089246,0.033274,-0.060316,-0.101888,0.062061,0.042849,0.032732,0.039839,0.048216,0.07807,-0.053718,-0.046098,0.075497,0.109739,0.035583,-0.067365,-0.016878,0.001368,-0.06477,-0.125475,0.044151,-0.009118,-5.3e-05,-0.0,-0.065095,-0.016612,-0.020789,0.038786,0.00804,0.001414,0.062624,0.061852,0.057369,0.111101,0.022792,0.049432,0.114809,-0.010634,-0.031781,-0.152179,0.032265,0.002143,-0.072784,-0.017436,0.021018,0.017226,0.005894,0.042439,0.013503,-0.003109,0.008637,0.040481,0.007733,-0.034711,0.056602,0.07146,-0.127251,0.016852,-0.013658,-0.092519,0.09091,-0.068798,-0.028987,0.009316,-0.012385,0.0462,-0.023098,-0.01169,-0.032303,-0.010817,-0.024687,0.018924,0.100526,0.015035,0.06345,0.054726,-0.010581,0.013134,0.00741,0.044649,0.038922,-0.059248,0.035802,-0.011184,-0.072293,-0.009331,0.038673,0.036149,0.019405,0.028871,0.015095,0.035081,0.070344,-0.035085,-0.012201,-0.031565,0.004147,-0.001484,0.031048,0.019423,0.025641,0.036562,0.085916,0.001928,0.083441,0.041342,0.057533,-0.008988,0.007998,-0.042809,0.010652,-0.050549,0.074038,-0.033753,-0.010267,-0.043391,0.054859,-0.023627,0.019225,-0.0,0.020182,-0.033593,0.048357,-0.012742,-0.024351,-0.002264,0.019633,0.069736,-0.056507,-0.064094,0.016848,-0.014757,-0.083948,-0.081428,-0.031896,-0.080695,-0.016568,-0.056227,0.003818,0.003834,0.05208,0.000421,0.024977,-0.086471,-0.018039,-0.01014,0.044714,0.078819,-0.033503,-0.066829,-0.029878,-0.090155,-0.041987,-0.007179,-0.060228,0.04287,0.020628,0.054185,-0.006634,-0.033201,-0.010973,-0.116181,0.042471,-0.047177,-0.046508,-0.028717,-0.056439,-0.033303,0.064588,-0.010353,-0.056226,-0.038539,0.038114,0.054356,-0.015065,-0.049148,-0.028673,-0.080725,0.043957,0.02689,-0.007601,-0.028994,-0.088828,0.028808],"category":"Lottery Scam","source":"seed_minilm"},{"embedding":[-0.015781,0.022431,0.08493,-0.078548,-0.003231,-0.026838,0.092949,0.018792,-0.001324,0.013292,0.073571,-0.059369,0.047632,0.039517,-0.001654,0.04129,0.070619,-0.058409,-0.064894,-0.023155,0.015907,-0.014911,-0.02495,-0.033679,0.071044,-0.023705,-0.065375,0.0237,-0.039624,-0.001571,0.04512,0.056944,0.022986,0.016188,0.016948,-0.103911,-0.061245,-0.027721,0.005038,-0.020967,-0.001668,0.02436,-0.050632,0.081687,0.016197,0.044047,0.044532,0.081606,0.075252,0.024168,-0.018523,0.048562,-0.052826,0.035129,-0.055053,0.006074,0.054901,-0.000174,0.034253,-0.011874,0.039903,-0.030651,-0.103913,0.019506,-0.037269,-0.102061,-0.069961,-0.001446,-0.021446,-0.049681,0.107453,-0.006663,0.064453,0.00645,0.065826,0.099736,-0.061709,-0.057117,-0.019359,0.043256,-0.075632,-0.035755,0.01539,0.030917,0.044782,-0.011844,0.01465,0.037132,0.002591,-0.033188,0.022304,0.031126,-0.059976,-0.001228,-0.030685,-0.003789,0.010207,-0.060693,-0.021924,0.050447,0.041162,0.021376,-0.050852,-0.011617,0.096172,-0.035576,-0.076216,-0.027334,0.037534,0.068953,0.038317,0.029617,0.067609,0.04608,-0.013788,0.070775,-0.0848,0.13259,0.088472,-0.001349,-0.019919,0.035663,0.00328,-0.082592,-0.126382,-0.105439,0.087992,-0.0,0.00734,0.040505,-0.025789,0.067373,-0.032655,-0.081582,0.00261,0.052631,-0.040258,-0.043892,-0.067491,-0.095831,0.047624,-0.033445,-0.033808,0.004167,-0.005551,-0.060388,0.064948,0.084328,-0.013271,-0.08011,0.005026,-0.020163,-0.004556,0.075769,-0.010522,-0.043373,0.066993,0.005748,-0.013874,0.043401,-0.030823,-0.033449,-0.023649,0.046128,0.087233,-0.112291,0.03552,0.031086,-0.108862,-0.051515,-0.048126,-0.024439,0.04333,0.001158,-0.037855,-0.015864,0.084994,0.036523,-0.0813,0.000632,-0.016865,-0.057481,-0.042701,-0.063605,0.020093,-0.017938,-0.053626,0.006541,-0.011631,-0.028814,-0.035481,-0.030325,-0.100216,-0.042833,-0.020347,-0.124102,-0.000259,0.059446,0.028821,0.042746,0.067302,-0.026935,0.020916,0.038621,0.035728,-0.031798,0.045937,0.004289,-0.05261,0.105984,-0.037764,-0.002587,0.080389,0.062992,-0.010339,-0.061892,0.001298,0.07601,-0.039089,-0.044304,-0.015799,0.000644,-0.029508,-0.0,-0.074595,-0.012056,-0.006977,-0.014293,0.051158,-0.018958,-0.008787,0.086533,-0.023478,0.075795,0.041036,0.008572,0.088068,0.016763,0.033797,-0.06489,-0.001047,0.016286,-0.018793,0.031605,0.012389,0.052995,0.036364,0.012622,-0.02907,-0.063202,0.058657,0.037193,0.003049,-0.012394,0.129479,-0.071898,-0.124979,0.05444,0.004642,0.007831,0.028135,-0.011373,0.066405,-0.018353,-0.004105,0.017535,0.019257,0.016101,-0.019255,-0.036762,0.022587,-0.027553,0.084727,-0.046722,0.066505,0.032955,-0.085736,0.077412,-0.089186,0.052219,0.045593,0.016288,0.026096,-0.039474,0.011425,0.014991,-0.017283,-0.034216,0.013958,-0.008837,0.014443,-0.020357,-0.013567,0.087764,-0.073916,0.057839,-0.02473,-0.039914,0.045351,0.056979,0.01844,0.136728,-0.025058,0.001152,0.059494,0.083821,0.075875,-0.044769,0.043182,0.025154,0.072635,-0.067944,0.039206,0.059707,-0.032422,0.003681,0.010148,-0.089864,-0.057039,-0.0,0.023188,0.015151,0.058075,-0.00846,-0.041207,0.045244,-0.007682,0.035101,0.041652,-0.036408,-0.003174,-0.054514,-0.155131,-0.024229,0.053271,-0.065851,0.014322,0.070996,0.009848,-0.087564,0.066679,0.062207,-0.047877,-0.008989,-0.067959,0.05438,0.056823,0.013263,0.010872,-0.067246,0.018021,-0.042062,0.017793,-0.049542,-0.057901,-0.106547,-0.0285,-0.042591,0.050485,0.050498,0.050612,-0.059081,-0.008915,0.00659,0.00267,0.052896,-0.048596,-0.086808,0.033551,0.048202,0.007026,-0.074277,0.03222,-0.000818,-0.022386,-0.07678,0.014821,-0.063999,-0.002314,0.024003,0.071058,-0.074138,-0.073406,-0.028682],"category":"Lottery Scam","source":"seed_minilm"},{"embedding":[-0.073923,0.032283,-0.026736,-0.018728,-0.022706,-0.006927,0.037945,-0.029057,-0.008463,0.017345,-0.033426,0.082692,0.067721,-0.006804,-0.050768,0.048644,0.049935,-0.064476,0.01327,-0.028686,-0.037574,-0.041211,-0.006258,0.026767,0.013763,0.00208,-0.031804,0.045535,-0.02002,-0.078162,0.06903,0.115998,-0.048974,-0.038933,-0.021043,-0.018615,-0.052645,-0.123063,0.001214,-0.040599,0.079911,0.01381,0.021348,0.075678,-0.003396,-0.016378,0.062934,0.09088,0.119245,0.015509,-0.05105,-0.01682,-0.033903,-0.037968,-0.069932,0.03097,0.044975,-0.029635,-0.015847,-0.020028,0.102719,-0.073731,-0.000576,0.043546,-0.006395,0.036713,-0.027804,0.047332,-0.042152,-0.078714,0.027211,-0.048266,0.046643,0.039205,0.065181,0.033087,0.042173,-0.137711,-0.048415,0.055708,-0.164438,-0.125687,-0.054973,-0.075908,0.043676,-0.014057,0.047829,0.050448,0.022377,-0.029623,-0.053592,0.00419,0.005293,0.021029,-0.0342,-0.00016,0.001551,-0.015427,-0.079056,0.035011,0.052246,0.066718,-0.014215,-0.054521,0.009088,-0.070138,0.006697,0.041215,-0.000907,-0.050284,-0.074641,0.087721,0.047005,-0.001003,-0.061644,0.023666,-0.040689,0.067188,0.112535,0.001148,0.074839,0.093895,0.036704,-0.052844,-0.008528,-0.079638,0.029114,-0.0,-0.046119,0.126964,0.034738,0.022604,-0.028413,0.070901,-0.007596,-0.001042,-0.065685,0.009774,-0.018896,0.022664,0.038905,-0.089727,-0.052164,-0.019465,-0.044535,-0.014698,0.007273,0.010094,-0.011216,0.021106,-0.009342,0.006705,0.009171,-0.015166,-0.033964,0.020597,0.047051,0.033572,0.04846,0.017571,-0.039275,-0.017102,-0.062375,-0.034217,-0.046511,-0.090756,0.012552,-0.023792,-0.068647,-0.015774,-0.058114,0.04947,-0.099062,0.070809,0.023904,0.030424,0.081218,0.022866,-0.071794,-0.031631,-0.026593,-0.037249,-0.020675,-0.10232,0.038575,0.025225,0.039133,-0.007301,0.090576,0.010905,-0.019949,-0.034621,-0.095256,-0.010374,0.067727,-0.025637,-0.024686,0.089255,0.053829,0.020118,0.027721,-0.021375,0.038479,-0.0053,-0.011279,0.010557,0.064619,-0.026417,0.005428,0.021056,-0.015918,0.003046,0.046395,0.093379,-0.027664,-0.108006,0.023774,-0.030008,-0.001655,0.020985,0.073379,-0.007042,-0.020412,0.0,-0.06203,-0.022158,-0.003374,0.061119,0.02646,0.003156,0.055328,0.073366,-0.063843,0.041897,0.019255,-0.003826,0.058183,0.019573,-0.005269,-0.06105,0.082948,-0.013346,0.026923,-0.038054,0.019868,0.108677,-0.026846,0.017406,-0.023982,-0.00195,0.039704,0.005039,0.003505,0.03132,0.002182,-0.020256,-0.106005,0.012791,-0.049048,0.073317,0.025244,-0.060652,-0.019779,-0.059254,-0.013191,-0.000318,-0.034493,0.006691,-0.054358,-0.101597,-0.025715,0.053624,0.043583,0.013332,-0.049998,0.01884,0.054651,-0.039626,-0.045782,0.095834,-0.00508,-0.037853,0.110241,-0.035211,-0.064184,0.014539,-0.045793,0.012424,-0.0414,-0.04297,0.142644,-0.032326,0.05667,0.044731,-0.029029,0.11158,0.008454,-0.090353,-0.029856,0.138063,0.058671,0.057705,0.030018,-0.073231,0.023156,0.084491,0.069528,0.011497,0.075475,-0.010027,-0.012878,-0.088636,0.008597,0.019537,0.001477,0.015915,-0.018619,0.020294,0.069399,-0.0,0.015366,0.017896,0.050388,-0.004958,0.079994,0.022553,-0.030974,0.012253,-0.004579,0.061463,0.024211,-0.054121,-0.037819,-0.039496,-0.023399,-0.036928,-0.029349,0.039437,0.01903,-0.055184,0.054617,-0.019116,0.09141,-0.075396,-0.010711,0.059757,0.002174,0.030893,0.06106,-0.088157,-0.014816,-0.037037,0.019581,-0.045096,-0.078641,-0.084106,-0.016541,0.076206,-0.006405,0.006382,0.005286,-0.046597,0.00064,0.025459,-0.092278,-0.006533,-0.0559,-0.043478,0.030019,0.002554,0.014504,-0.111322,0.01037,0.042505,0.044938,-0.00818,-0.02091,-0.02284,-0.008981,0.07632,0.042942,-0.121919,-0.128441,0.015992],"category":"Lottery Scam","source":"seed_minilm"},{"embedding":[0.01158,-0.047179,0.023915,0.017492,0.01234,-0.010459,-0.030958,-0.01511,-0.003099,0.064734,-0.032067,-0.058929,-0.011432,-0.023952,0.026833,-0.025382,0.009001,-0.04152,-0.084419,0.052155,0.070236,0.053661,-0.019782,-0.049368,-0.030162,-0.019465,-0.101021,-0.057864,-0.105871,-0.06238,0.018972,0.022801,-0.059125,-0.010605,0.07262,0.04888,-0.029085,0.032715,0.140523,-0.070791,0.04244,0.022635,0.059791,0.026784,0.067228,-0.038632,0.027165,0.041099,0.040113,0.025261,-0.014452,-0.011109,-0.077299,0.00661,0.006504,0.033542,0.090439,-0.011955,-0.008331,-0.032378,0.021871,-0.014635,-0.039389,0.000629,-0.069596,-0.025652,0.004148,-0.059595,-0.003233,-0.048357,0.01739,0.06894,-0.058688,0.031017,0.038408,-0.031046,0.067087,0.067642,0.057266,0.045595,-0.013275,-0.04794,0.10044,0.030657,-0.006863,-0.045943,0.030042,-0.000593,-0.095988,-0.080641,0.063037,0.039157,-0.016739,0.028123,-0.059069,-0.030498,-0.020113,0.076312,-0.112562,0.047537,0.074701,0.008578,-0.129866,0.072402,-0.09077,-0.043546,-0.07071,-0.03228,-0.069398,0.01737,-0.007282,0.011655,0.018259,-0.009339,-0.094367,0.031987,-0.019793,0.036993,0.028034,-0.104545,-0.0778,0.026935,-0.009283,-0.056722,-0.05488,-0.085306,0.133639,-0.0,-0.081077,-0.015265,0.024774,-0.070603,0.057247,-0.057881,-0.01397,-0.055298,0.036372,-0.030516,-0.079149,-0.080633,0.040367,-0.031381,-0.076691,0.010937,0.04914,0.060882,0.035759,0.018289,-0.049925,-0.07042,0.023182,-0.022078,-0.050314,0.073215,0.038053,0.098854,0.05006,0.00785,0.004606,-0.016202,0.048441,0.082126,-0.025439,-0.038186,-0.013223,-0.054082,-0.050648,-0.010323,0.046951,0.037343,-0.03228,0.056117,0.067573,0.072755,0.040848,0.041824,0.061473,0.058539,-0.096476,0.047765,0.057593,-0.059999,-0.027593,0.028733,0.023037,-0.019225,0.006207,0.016881,0.007211,-0.034725,-0.013996,-0.038131,0.042769,-0.067505,-0.052894,-0.001607,-0.006041,0.024255,0.058271,0.078451,0.113192,0.061998,-0.005627,0.01819,0.016484,-0.004052,-0.048462,-0.074356,-0.018246,0.029288,-0.009308,-0.027672,0.038261,0.022899,-0.062799,0.158074,0.076691,0.053896,0.018366,-0.00582,-0.023246,0.010319,0.030558,0.0,-0.027615,0.035804,-0.185299,0.047212,-0.016366,0.042531,-0.010177,0.013863,0.085973,0.04806,-0.024544,0.011082,0.060484,-0.053786,-0.037889,-0.000159,0.021093,0.027375,-0.077903,0.058798,0.030654,0.045051,-0.056357,0.029969,0.031668,0.039847,-0.007518,0.067793,-0.030061,0.01308,0.030477,-0.051627,-0.107541,0.12053,-0.024966,-0.030541,-0.00023,0.013713,0.141751,0.095262,-0.108634,0.112129,-0.003144,-0.00822,0.096967,-0.059601,0.009717,-0.038072,-0.017418,0.021752,-0.063282,0.003953,0.011886,-0.069498,0.000175,0.068689,0.024319,-0.005784,0.045443,-0.001835,0.014478,-0.028112,0.045928,-0.006281,0.086053,0.08163,0.017063,-0.010972,0.119341,0.078677,0.010735,-0.030105,-0.016914,0.048653,-0.019103,-0.017759,0.005359,0.084987,-0.085233,0.047377,0.052644,0.008736,0.027697,-0.019815,-0.017855,0.007599,0.064122,-0.017084,0.065705,-0.003562,-0.020465,0.012896,-0.074196,0.003211,-0.002406,-0.0,0.015007,-0.03863,-0.070183,0.019038,0.01918,0.030198,0.008661,-0.050722,-0.024439,-0.049917,-0.082485,-0.008976,-0.016138,0.049926,0.010848,-0.045832,-0.036333,0.051627,-0.032832,-0.120478,0.013658,0.011848,0.098317,-0.073865,0.041941,-0.004118,0.003622,-0.042899,0.010036,0.003423,-0.058606,-0.010081,0.042333,-0.080227,-0.028074,0.013375,0.003673,0.058047,0.015551,0.068752,0.044124,0.019972,-0.015518,0.004386,0.041278,-0.023745,-0.062177,0.010974,0.005286,0.051247,0.005372,-0.019974,-0.023075,-0.012277,-0.055563,0.033335,-0.103899,-0.042018,-0.000219,0.046709,-0.010075,-0.003841,-0.020413,-0.057066],"category":"Delivery Fraud","source":"seed_minilm"},{"embedding":[-0.05351,-0.033695,-0.020575,-0.06037,0.021071,0.011754,0.019403,-0.005109,-0.029436,0.059312,0.091192,-0.078872,0.002719,-0.001264,-0.00069,-0.013764,0.079104,-0.029967,0.011347,0.037796,0.011424,0.104933,-0.033274,-0.010059,0.022035,0.003072,-0.022761,-0.022885,-0.004143,-0.02379,-0.008094,0.034318,-0.048488,0.06233,-0.012974,-0.01348,0.014952,-0.030164,0.097103,-0.060679,0.054268,-0.044893,-0.05322,0.053864,-0.020008,-0.021152,0.040311,0.041939,-0.003525,0.051449,0.097069,0.057033,-0.079157,0.093946,-0.049781,-0.017437,0.083565,0.049571,-0.003403,0.025368,-0.02437,0.035069,-0.072713,0.039444,-0.010497,-0.06678,-0.036101,-0.002301,-0.029691,-0.092616,-0.028168,-0.001378,-0.001608,0.005188,-0.023524,-0.023339,0.046558,-0.070316,-0.082109,-0.043553,0.028884,0.072509,-0.027192,0.045219,-0.017809,-0.002391,0.042585,0.053967,-0.002785,0.013929,0.079463,-0.060298,-0.020294,0.038749,-0.128464,-0.010547,0.014319,0.062761,0.00029,-0.013915,0.02765,0.041938,-0.096459,-0.002875,-0.065939,-0.030266,-0.040568,-0.034976,0.006126,0.053245,-0.02096,0.053763,-0.084489,-0.021957,-0.085963,0.09446,-0.092417,0.017945,0.016763,-0.101859,-0.023441,0.018196,-0.043523,-0.026982,-0.066305,-0.080533,0.145508,-0.0,-0.0248,0.024011,-0.054486,0.013528,0.060196,-0.064131,0.01424,0.011956,0.030951,0.047337,-0.0979,-0.018553,-0.015692,0.000132,-0.130543,-0.014021,-0.014094,0.037567,0.121444,0.10486,-0.009022,-0.06356,-0.020279,0.027013,0.012912,0.09071,-0.008799,0.018891,0.078201,0.061287,-0.013404,0.008678,0.059293,0.042198,0.059408,0.031723,-0.023347,-0.016924,-0.048839,-0.04303,0.018476,-0.048351,-0.094724,0.011363,-0.07329,0.004729,0.047764,-0.011527,0.067363,0.029152,-0.013564,-0.034735,0.004421,-0.05304,0.012929,-0.13831,0.030777,-0.050075,0.025586,0.019479,0.025562,-0.048078,-0.002588,0.034439,0.04037,-0.116609,-0.051388,-0.034787,-0.003365,-0.070122,0.004088,0.082816,0.072976,0.018721,0.067804,0.07188,0.009852,0.057868,0.106797,-0.039608,-0.101688,-0.022688,-0.014279,-0.005013,0.123776,0.042749,-0.021249,0.068375,-0.024726,0.028914,-0.054783,0.022744,0.018593,0.013315,0.078531,-0.0,-0.013578,0.045984,-0.114901,0.032262,0.001978,0.016148,-0.016898,0.091932,0.001998,0.072488,-0.086911,0.005713,-0.035506,-0.013145,0.062049,-0.089894,0.013349,0.052001,-0.09466,0.039571,-0.015593,-0.01854,-0.015483,0.008812,0.01337,0.035918,0.001068,0.046368,-0.029951,0.046239,0.022882,-0.029008,-0.080467,0.043502,-0.08257,0.021204,0.024366,0.06952,0.089561,0.029034,-0.075271,0.035882,-0.021248,0.082395,-0.051065,-0.11671,0.031167,-0.068495,0.057282,0.0177,0.028721,0.022776,0.048491,-0.025637,-0.022434,0.147938,0.027143,0.029662,0.058401,-0.099671,0.061459,0.063074,-0.027584,-0.012951,-0.000516,-0.003756,0.090478,0.023182,0.033431,0.028936,-0.021933,-0.025725,-0.044235,-0.053934,0.042319,-0.092161,0.008064,0.024167,0.037171,0.059351,0.02436,-0.019951,-0.015985,0.025052,-0.008131,-0.033597,0.043872,-0.034848,0.041595,-0.019446,-0.079984,0.047881,-0.045748,0.017187,-0.0016,-0.0,-0.012711,0.001398,-0.045863,0.051618,0.02739,0.047537,-0.03026,0.092477,-0.027945,-0.038641,0.009996,-0.053945,-0.072233,0.000192,0.025031,-0.052095,0.004045,0.002698,-0.110129,-0.114505,-0.042686,0.026799,0.096933,-0.009038,-0.044683,0.013162,0.011027,0.044818,0.095568,-0.010586,-0.003731,0.0303,-0.083472,-0.05064,-0.027021,-0.043285,-0.003944,-0.007507,0.067141,0.079759,-0.014292,-0.023761,-0.034881,0.063881,-0.010106,0.012891,-0.123157,-0.049493,-0.038648,-0.017238,0.035252,-0.042353,-0.060632,0.035449,-0.045912,0.027098,-0.049812,-0.028299,-0.046034,0.046297,-0.056602,0.002415,0.004569,-0.026472],"category":"Delivery Fraud","source":"seed_minilm"},{"embedding":[0.014653,0.00914,0.03461,0.064759,-0.004599,-0.041336,-0.035242,-0.010305,0.02503,0.05205,0.02074,-0.066335,0.02125,0.006916,-0.083945,-0.018792,-0.001801,-0.092707,-0.113166,0.024328,0.018162,0.075897,-0.033285,0.038261,-0.065677,0.010199,-0.128193,0.039618,-0.030896,-0.064031,0.026634,0.031839,-0.04281,0.071161,0.095564,0.047686,0.009307,-0.11154,0.057924,-0.029315,0.037219,0.054786,0.047773,0.052131,0.044773,-0.037795,0.050574,0.013107,0.099099,0.094972,-0.016687,-0.036897,-0.053065,0.027364,-0.014398,0.089045,-0.04866,-0.009324,-0.003744,-0.042877,0.093219,-0.054377,-0.040239,0.01433,-0.01749,0.020208,-0.035229,-0.061654,-0.067655,-0.035794,0.059715,-0.022722,-0.062598,0.115674,-0.003393,-0.021553,0.109467,-0.063587,0.019268,0.023039,-0.052272,-0.055359,-0.076387,-0.012521,-0.003271,-0.058344,0.045777,0.102618,-0.020457,-0.038867,0.011903,0.002547,-0.007676,0.036171,-0.07315,-0.046296,0.061215,0.047672,-0.016085,0.053235,0.111195,0.027966,-0.042121,0.009087,-0.054728,-0.047686,-0.029138,0.026625,-0.037456,-0.018443,-0.071212,-0.013543,0.0435,-0.02209,0.000749,0.139253,-0.100364,0.02006,0.068374,-0.102688,-0.044658,0.045875,-0.000353,-0.046184,-0.024766,-0.012155,0.111593,0.0,-0.087396,-0.025717,0.000685,-0.012994,0.096413,-0.025598,-0.025711,0.001209,-0.001896,-0.069587,-0.077559,-0.06961,0.029395,-0.098898,-0.125751,-0.007917,0.066198,0.03995,-0.017718,0.088879,-0.056701,-0.076634,-0.022229,0.016652,-0.05723,0.032877,0.013865,0.030385,0.043985,0.017483,0.041998,-0.007625,-0.004327,0.020325,0.006689,-0.037773,-0.033732,0.018963,-0.04966,-0.073832,-0.000288,0.006641,-0.08781,0.055505,0.033164,0.063801,0.065217,-0.011879,0.083493,-0.00795,-0.107386,0.034423,0.071469,-0.019906,0.002424,-0.041708,0.000919,-0.005135,-0.032594,-0.008299,0.074981,-0.017213,-0.048271,-0.041731,0.018675,-0.142441,0.017481,0.064475,0.049099,0.035172,0.058838,0.031774,0.107469,0.037386,0.111449,-0.005467,0.022692,-0.002165,0.002786,-0.079448,0.007666,0.040853,-0.03327,0.005508,0.001923,0.057065,0.022849,0.021272,-0.002052,0.056889,-0.033897,-0.018069,0.020852,-0.015135,0.027241,-0.0,-0.012389,0.066558,-0.095837,0.050272,0.037097,-0.020491,0.032873,0.051603,0.023043,0.012019,-0.001613,-0.082207,0.086572,-0.006855,-0.019237,-0.050502,0.075869,-0.05012,0.002892,0.034996,-0.004098,0.060307,-0.04134,0.021414,-0.047802,0.110844,0.046468,0.02657,-0.065907,0.009465,0.000549,-0.024451,-0.082743,0.145802,-0.008532,-0.028121,0.019176,0.011322,-0.031279,-0.048191,-0.010796,0.057983,-0.019808,0.044617,0.025144,-0.003404,0.028571,-0.051762,-0.022574,0.057786,-0.078036,-0.018726,-0.014481,-0.015233,-0.003415,0.081943,0.035629,-0.039605,0.07225,-0.001134,-0.094063,-0.045547,0.051884,-0.044503,0.030771,-0.002926,0.069175,-0.001565,0.106549,0.030899,0.022539,0.034672,0.043463,0.015891,0.028768,0.016511,-0.059858,-0.011429,-0.101901,-0.016961,0.055798,0.022956,-0.006115,0.034955,0.044073,0.015507,0.079716,0.016868,0.018745,-0.014554,-0.002019,-0.00289,-0.072355,0.048043,-0.008458,-0.0,-0.027275,-0.027665,0.039081,-0.04459,0.079803,0.013479,0.078141,-0.012361,0.00711,0.017763,-0.099042,-0.062383,-0.058324,0.063889,-0.024194,-0.065012,-0.017273,-5e-06,-0.015568,-0.151703,-0.050971,-0.007876,0.06786,-0.076384,0.022329,0.02155,-0.034084,0.041032,0.055581,-0.028461,-0.002896,-0.017579,0.040335,-0.099164,-0.085132,-0.063385,0.028727,-0.018638,0.014051,-0.079016,0.040461,-0.002379,0.058392,-0.007512,-0.007379,-0.04232,-0.015118,0.026116,0.028524,0.025952,-0.012845,-0.11058,-7.4e-05,0.0002,0.026591,-0.065902,-0.021922,-0.053145,-0.018671,0.032288,0.046817,-0.024295,-0.055531,-0.004431],"category":"Delivery Fraud","source":"seed_minilm"},{"embedding":[-0.01682,-0.102123,-0.018686,-0.001215,0.01111,-0.019298,-0.021515,-0.035216,-0.021858,-0.059171,0.037553,-0.062824,0.012369,-0.000694,-0.042231,0.011321,0.006851,-0.047134,0.016616,-0.01457,-0.010534,0.107971,-0.039149,0.047352,0.031568,0.00213,-0.057733,-0.023487,-0.057884,-0.058459,0.077653,0.021384,-0.052392,0.020855,0.102592,-0.010027,-0.027171,-0.063519,0.166465,-0.087671,0.015284,-0.023124,0.003083,0.037102,-0.007036,0.038707,0.067229,0.001712,0.007756,0.011556,0.026468,-0.002846,-0.000492,0.000536,-0.094447,-0.00159,0.005217,0.051262,0.000931,-0.012942,0.022294,0.034959,-0.00243,-0.013071,0.008185,-0.050292,-0.041864,-0.000335,-0.043995,-0.049916,0.075236,0.009168,-0.010903,0.113161,-0.021627,-0.001627,-0.003419,0.01322,-0.020709,0.010536,-0.000723,-0.014861,0.023742,0.073959,-0.011892,0.048306,-0.00482,0.06357,-0.039176,-0.043596,0.016605,0.031898,0.023882,0.033827,-0.020355,-0.02244,-0.024576,0.068051,-0.079712,0.042199,0.038913,0.029955,-0.111114,0.067642,-0.032965,-0.03936,-0.081365,-0.009821,0.070712,0.082059,-0.02174,0.029463,-0.015229,-0.007191,-0.083682,0.035796,-0.02069,0.027208,0.003441,-0.090493,-0.078762,0.024211,-0.002464,-0.092866,-0.031192,-0.09176,0.136229,-0.0,-0.099763,0.014299,0.093013,0.003586,-0.034866,-0.086143,-0.019943,-0.042956,0.037337,-0.064787,-0.054295,-0.048095,0.060011,-0.0126,-0.015317,0.004661,0.036292,0.047795,0.04641,0.061678,0.016439,-0.073351,0.018903,0.001229,-0.04395,0.060499,0.07192,0.046636,0.035328,0.048614,0.042358,-0.025868,0.040726,0.038664,0.02628,0.029239,-0.033891,-0.062377,-0.071695,0.005439,0.066349,-0.025052,-0.02335,0.066201,-0.015412,0.054252,0.104883,0.036068,0.023004,0.060816,-0.067991,0.030994,-0.037114,-0.049905,0.006381,-0.041643,-0.000664,-0.01562,0.008848,-0.050695,0.077317,-0.026478,-0.096785,-0.066415,0.003252,-0.103391,-0.00915,0.002892,0.015933,-0.053804,0.037766,-0.046528,0.025651,0.104484,0.008484,-0.006924,-0.03282,0.0291,-0.014588,-0.053546,-0.076595,-0.072513,-0.024856,-0.046609,0.026804,0.025382,0.009604,0.059229,-0.081129,0.065517,0.021742,0.039652,-0.027314,0.019958,0.037676,-0.0,-0.08205,0.01505,-0.128753,0.039807,-0.002727,0.031844,-0.000657,0.052461,0.065871,0.060053,-0.081811,0.030679,0.062639,0.036928,-0.019975,0.014663,-0.026643,0.063761,-0.080382,0.052139,-0.004902,0.032535,-0.030829,-0.001344,-0.037475,0.075508,0.029503,0.040421,0.018334,-0.0175,0.045922,0.01944,-0.066081,0.071797,-0.039749,-0.076256,0.038104,0.021906,0.100205,-0.012619,-0.123477,0.110229,0.012755,0.039108,-0.025299,-0.14217,0.060503,0.019393,0.067477,0.017492,-0.046008,0.066876,0.054664,-0.056669,-0.023444,0.113338,-0.003081,0.006718,0.055393,-0.065382,-0.03883,0.123585,-0.002811,0.049703,0.126688,-0.011609,0.078412,-0.027412,0.063759,-0.042793,-0.015125,-0.008865,-0.029473,-0.062589,0.082448,-0.023449,-0.053309,0.101598,-0.04492,-0.012231,0.070621,-0.022151,0.024608,-0.017219,0.090701,-0.053566,-0.009758,-0.033262,0.006822,-0.018491,0.004713,0.014412,-0.061437,-0.015183,-0.03932,-0.0,0.003364,-0.066397,-0.023673,0.041564,0.072052,0.012347,0.028903,0.035188,-0.020689,-0.046117,-0.075953,-0.085191,-0.109251,0.020305,-0.062284,-0.14882,-0.030841,0.012432,-0.074598,-0.077025,-0.069005,-0.04426,0.07689,-0.084791,0.02914,0.031837,0.016632,-0.001354,0.063554,-0.0113,-0.02589,0.026336,0.014394,-0.094967,-0.057904,0.005148,0.097554,0.036242,0.001586,-0.011731,0.001626,-0.013023,0.041494,0.011483,0.024385,0.041753,-0.022475,-0.034031,-0.006599,-0.037717,-0.019656,-0.03048,-0.026951,0.087735,-0.048474,0.018531,-0.093602,-0.036281,0.01639,0.050404,0.035381,0.002582,-0.051373,0.011109],"category":"Delivery Fraud","source":"seed_minilm"},{"embedding":[-0.051473,-0.02756,-0.003976,-0.003561,-0.037747,-0.024082,0.065547,-0.013112,-0.022999,0.098044,0.06751,-0.087338,-0.044959,-0.040621,-0.008601,-0.040402,0.051499,-0.035984,-0.057507,0.015361,-0.03691,0.049008,-0.003566,0.002285,-0.000409,-0.032953,-0.066396,-0.001007,-0.019547,-0.0742,-0.019818,0.078822,-0.055621,-0.002236,0.050654,0.001873,-0.056593,0.013077,0.081534,-0.017048,0.045292,-0.051195,-0.004349,0.051161,0.024113,0.024392,-0.043577,0.099157,0.009355,0.07016,0.029921,-0.072507,-0.041809,-0.006931,0.029692,0.00702,0.03969,0.003152,-0.018403,0.014842,-0.028095,0.042015,-0.111094,0.036132,0.013986,0.000987,-0.026389,-0.019009,-0.02346,-0.08522,0.027315,0.077161,0.031241,0.064766,-0.012342,-0.03469,0.074218,0.022902,-0.002441,-0.006697,-0.019791,-0.03019,0.040909,0.018989,-0.034085,-0.060967,0.032826,0.048395,-0.007102,-0.021869,0.053676,0.050216,0.01657,0.007369,-0.107575,0.058358,-0.009213,0.024041,-0.084299,0.033792,0.08993,0.057808,-0.075642,0.014071,-0.084162,-0.063253,0.036586,-0.016028,0.031852,0.010818,-0.065878,-0.001823,-0.032044,-0.122364,-0.087126,0.075964,-0.047753,0.011856,0.08928,-0.135535,-0.06005,0.02385,-0.001779,-0.113711,-0.081126,-0.031448,0.082601,0.0,-0.128657,-0.031601,-0.037902,-0.014192,-0.005001,-0.065676,0.026064,-0.053602,-0.034303,-0.063029,-0.09832,-0.061538,-0.046859,-0.036224,-0.029963,-0.044855,0.07694,0.100287,0.086708,0.056315,-0.025095,-0.060055,-0.005908,-0.041937,0.080481,0.003504,0.04847,0.053881,0.122809,0.034425,0.034635,0.043612,0.040068,0.002148,-0.02389,-0.003488,-0.034005,-0.052179,-0.005835,-0.068801,-0.047784,0.054188,-0.129039,0.021578,-0.056708,0.035145,0.002384,-0.037406,0.040135,-0.015348,-0.038599,0.047434,-0.049654,0.043009,-0.027093,0.019334,0.056449,-0.041733,-0.034184,0.035786,0.057993,-0.025669,-0.012393,-0.056144,0.004321,-0.023192,-0.027588,-0.118007,0.000639,-0.017192,-0.033325,0.025075,0.023614,0.023855,-0.004905,0.057473,-0.050007,0.020126,-0.001486,-0.01523,-0.012177,-0.004769,0.002238,0.010239,0.12051,-0.011886,0.000782,0.024488,0.004311,0.048293,-0.00562,-0.011562,-0.020246,0.06866,0.048851,-0.0,-0.018001,0.040715,-0.124276,0.08273,-0.011849,0.024009,-0.036575,0.032149,0.083234,0.026301,-0.098171,0.083082,-0.043357,0.016706,-0.000672,-0.048842,0.052147,0.028431,-0.001737,0.056249,-0.052705,0.012218,-0.130454,0.009978,-0.045583,0.082196,-0.034588,0.055647,-0.028364,-0.009664,-0.003379,-0.132055,-0.084335,0.039218,-0.017291,-0.017728,0.109257,0.098133,0.096617,0.095861,-0.042036,0.036997,-0.00826,0.024595,0.056757,-0.080939,-0.004762,-0.019792,-0.046926,0.007267,-0.032607,-0.060395,0.025157,0.02868,-0.013007,0.07476,0.024511,0.012793,0.04175,-0.02205,0.030802,0.032146,0.007033,-0.017279,0.034883,0.092062,0.081224,-0.023224,0.04753,0.031112,-0.056713,-0.034279,-0.035179,0.013594,0.024791,0.028834,0.086539,0.039848,0.053133,0.066349,0.048813,0.04985,0.007454,-0.005308,-0.004697,0.000193,0.129734,0.011546,0.028433,-0.015714,-0.042948,0.032072,-0.02362,-0.013174,-0.005084,-0.0,-0.047606,-0.005594,-0.039365,0.095275,0.033284,0.010141,-0.016387,0.041206,0.019771,-0.026681,-0.056863,0.016308,-0.054106,0.038162,-0.043648,0.003056,-0.052884,-0.006024,-0.065742,-0.096819,0.020184,0.031993,0.124019,-0.027446,0.050083,-0.040999,0.058966,0.04249,0.017361,0.016007,-0.060961,0.018207,0.018207,-0.041108,0.032015,-0.028454,-0.089522,0.006527,0.098419,0.057295,0.052392,-0.044864,0.043295,0.019403,0.124061,0.036338,-0.06888,-0.059677,0.011425,-0.05557,-0.035314,-0.019356,0.051214,0.063331,-0.001777,-0.02338,-0.05363,0.026338,0.030849,0.109807,0.001354,-0.09117,-0.026636,0.03498],"category":"Delivery Fraud","source":"seed_minilm"},{"embedding":[0.001995,-0.031442,0.013889,-0.005775,-0.006391,-0.06885,-0.011085,0.030207,-0.024038,-0.015042,0.068477,-0.051251,-0.053147,-0.002817,0.008304,-0.027065,0.03108,-0.021739,-0.038132,-0.02871,-0.062309,0.015699,-0.021857,-0.052844,0.020805,-0.013891,-0.046197,0.03124,-0.057353,-0.056786,0.087023,0.029537,-0.037418,-0.029678,0.084005,0.014862,-0.050183,-0.033856,0.047691,0.022693,0.027491,0.033121,0.039501,0.061585,0.049249,0.057137,-0.065973,0.070965,0.054157,-0.001449,-0.033157,-0.007655,-0.049686,-0.003565,-0.044708,0.020478,0.028956,-0.038224,0.026603,-0.058702,0.080517,-0.011176,-0.059795,-0.009218,-0.061539,-0.0235,-0.02124,-0.071692,-0.014331,0.006782,0.042199,-0.013442,-0.010417,0.092702,-0.038342,-0.002449,0.073385,-0.031421,-0.025258,0.026903,0.002536,-0.068785,0.002575,0.062233,0.02999,-0.033524,0.044216,0.061981,-0.013377,-0.015896,0.057552,0.036971,0.016672,-0.046677,-0.027089,-0.043323,0.045378,-0.022018,-0.090693,0.030052,0.041599,-0.028542,-0.032335,-0.004838,-0.039367,-0.045284,-0.078394,0.01027,0.018068,0.00613,-0.025508,0.014434,0.074409,-0.081035,-0.043655,0.08511,-0.101309,0.046685,0.026154,-0.064849,-0.002229,0.037386,-0.014722,-0.105488,-0.029216,-0.104144,0.059247,0.0,-0.03851,0.014695,-0.013121,-0.045708,0.045318,-0.021164,0.011996,-0.009143,-0.04824,-0.001148,-0.043217,-0.101867,0.021716,-0.04271,-0.158449,0.065311,0.061967,0.062396,-0.066005,0.032773,-0.039278,-0.087156,0.009517,0.00019,-0.013364,-0.012008,0.02552,-0.014274,0.080292,0.02992,0.064598,-0.026689,-0.01598,0.036962,0.010279,-0.009253,0.030363,-0.130024,-0.068317,-0.044353,0.008367,0.036247,-0.076104,0.071866,0.022451,0.038631,0.06352,0.009435,0.087943,0.094431,-0.154278,0.012212,-0.003613,0.073385,0.021582,-0.05185,0.027895,0.036967,-0.009888,0.000538,0.062061,-0.020328,-0.088562,-0.072787,0.022263,-0.043318,0.007137,-0.127122,-0.004531,-0.052728,0.055401,0.02109,0.084932,-0.003551,-0.012097,-0.029661,0.037136,0.057623,0.029203,-0.055097,-0.012328,-0.015665,-0.005476,-0.060888,0.074138,0.075608,0.005133,-0.035752,-0.02667,0.020367,0.010582,-0.008209,-0.000107,-0.003125,0.05853,-0.0,-0.106854,0.003068,-0.103606,0.099927,0.000575,-0.002537,0.019714,0.071355,0.033908,0.036421,-0.005972,0.054521,0.047218,-0.022161,0.009483,-0.046639,0.089774,0.034235,0.002745,0.023255,-0.007188,0.084847,0.014177,0.057061,0.047653,0.105485,0.070562,0.071499,-0.012272,-0.012946,0.077621,0.014465,-0.086517,0.12034,-0.056513,-0.020209,0.01845,0.074027,0.000313,0.044432,-0.031726,0.033099,-0.021572,-0.054913,-0.040763,-0.151701,0.004694,0.04384,0.053181,-0.040633,-0.034518,-0.00485,0.014179,4e-05,-0.007083,0.116843,0.090495,0.016486,0.049808,-0.012863,0.013341,0.004598,0.038178,0.027107,0.064494,0.107508,0.091688,0.011576,0.105677,-0.02241,-0.084185,0.041239,0.05709,-0.033331,0.023114,0.000201,-0.049816,0.077644,-0.007571,0.030517,0.077981,-0.042897,0.075897,0.064833,0.062803,-0.077904,0.029893,-0.007396,0.02171,0.014586,-0.031621,-0.019455,0.032135,0.08968,0.094804,-0.0,-0.009919,-0.031915,0.036151,0.028642,0.076814,0.026203,0.047536,-0.032834,-0.118212,0.010671,-0.113757,0.013572,-0.047509,0.048149,-0.003793,-0.047024,0.013025,0.041431,-0.047171,-0.07751,0.043683,-0.02203,0.064684,-0.054329,-0.00792,0.05194,0.088123,0.068841,0.067377,-0.087768,-0.090112,-0.013376,0.037957,-0.044128,-0.101544,-0.003716,-0.064901,0.027119,0.002556,-0.008986,-0.017293,0.030272,-0.014959,0.027383,-0.046806,0.031914,-0.076278,-0.010043,0.002765,-0.071917,0.003524,-0.035158,0.006928,0.069491,-0.045172,-0.011204,-0.025764,-0.018867,-0.022508,0.112165,0.040625,-0.055734,-0.04087,-0.017903],"category":"Delivery Fraud","source":"seed_minilm"},{"embedding":[-0.037426,-0.030098,-0.008691,-0.03596,0.040925,-0.020909,0.027661,0.007098,-0.107667,0.045321,0.083115,-0.083783,-0.006944,0.022085,-0.02404,0.091164,0.005566,-0.089647,-0.043212,-0.026369,-0.025672,0.105315,0.009763,0.033705,0.018008,0.011902,-0.022077,-0.021581,0.000453,0.032697,-0.063428,0.033931,0.011469,0.042674,-0.02131,-0.044746,0.003877,-0.014331,0.105487,-0.006017,0.035007,0.043781,-0.096704,0.063354,0.024938,0.00483,0.014052,0.012702,0.096352,0.01456,0.028716,0.057621,-0.057945,0.085555,-0.075296,0.04372,0.03568,0.006569,0.04181,-0.007659,-0.053935,0.013177,-0.043885,-0.021865,0.013896,0.00459,-0.093566,0.004634,-0.005217,-0.062663,-0.005444,-0.03455,-0.109656,0.020396,-0.002914,-0.028919,0.108693,-0.001056,-0.090854,-0.098181,-0.011922,-0.015937,0.008535,0.072938,-0.020354,-0.007374,0.013373,0.112445,-0.00836,0.013979,0.100894,-0.066064,-0.046343,-0.017582,-0.080318,0.004747,0.068728,0.008999,-0.022694,0.005738,0.065249,-0.008859,-0.133098,-0.041588,-0.09622,3.9e-05,0.035141,-0.012095,0.032551,-0.004398,0.02152,-0.058169,-0.005921,-0.042811,-0.049956,0.19369,-0.025138,0.024363,0.002281,-0.133035,0.031634,0.03359,0.009744,-0.075849,-0.051277,0.010301,0.056904,0.0,0.012404,0.039257,-0.051869,0.007519,0.004556,-0.003079,0.071998,0.020823,0.04791,-0.039069,-0.055681,-0.054164,-0.0305,-0.124411,-0.089698,-0.0074,0.044782,0.009386,0.043644,0.133913,-0.018702,-0.115766,-0.05239,0.004596,0.020779,-0.015785,-0.026664,0.037374,0.079461,0.047273,0.00411,0.089122,0.011111,0.036243,-0.041658,-0.026565,0.007513,-0.085857,-0.037691,-0.080991,-0.014172,0.008519,-0.1,0.064252,-0.036487,0.040152,0.085408,-0.000971,0.081687,0.06021,-0.119664,0.06909,0.048137,-0.10259,0.004235,-0.038412,0.0375,-0.020233,0.016999,0.015673,0.128031,-0.007272,-0.008299,0.049109,0.026497,-0.065542,-0.039955,0.001462,-0.033605,-0.082328,-0.02112,0.054081,0.098537,-0.023921,0.007003,0.022022,-0.02409,0.047997,0.026088,-0.065585,-0.096748,-0.017953,0.03223,0.012701,0.09628,0.044344,0.064291,0.069361,0.049675,-0.010216,-0.059328,-0.03287,0.016464,-0.019715,0.00704,-0.0,0.025505,0.025026,-0.151548,0.054393,-0.012122,-0.010351,0.048586,0.087668,0.03255,0.1216,-0.003738,0.051608,0.016698,-0.040937,0.054105,-0.016255,0.076835,0.070042,-0.051576,0.009402,-0.012521,0.003492,0.009823,0.019458,-0.015139,0.072306,-0.028436,0.02188,-0.082602,0.02128,0.002202,0.020639,-0.06009,0.016545,0.004101,-0.018538,0.035433,0.003987,0.074688,0.048284,-0.05402,0.0231,-0.03102,0.008538,-0.10198,-0.101589,-0.002516,0.008729,-0.009826,-0.0046,0.028604,0.065198,0.066286,-0.002144,0.037594,0.054576,-0.010285,0.083478,0.037456,-0.067364,0.04613,-0.009085,0.009542,-0.009991,0.037676,-0.013566,0.008649,0.039488,0.109534,0.001135,-0.046362,-0.073409,0.007802,0.049074,-0.002099,-0.011154,0.068597,-0.048934,0.011088,0.057555,0.043551,-0.001308,0.029316,-0.043448,-0.014692,-0.059349,-0.037532,0.017231,0.013765,-0.049622,-0.028157,-0.006971,0.007201,0.04198,0.014444,-0.0,0.023368,-0.039602,0.002416,0.086126,0.017462,-0.005743,0.01594,0.032793,-0.048675,0.015534,-0.028,-0.070553,-0.00877,-0.012832,-0.062522,-0.021298,-0.034288,0.003622,-0.069574,-0.095509,-0.027937,-0.010815,-0.006838,-0.003495,-0.037042,0.020167,0.004852,0.003601,0.136493,-0.054428,-0.013139,0.012657,0.011383,-0.018821,-0.027107,-0.038449,-0.066246,0.028226,0.032178,0.076084,-0.036041,-0.103476,-0.024352,0.005333,0.043846,-0.048857,-0.12508,0.009088,0.019806,-0.041042,0.02588,-0.090062,0.067208,0.042318,0.056964,-0.000612,-0.030382,0.010846,0.009485,0.018778,-0.034033,0.028024,-0.02336,0.002887],"category":"Delivery Fraud","source":"seed_minilm"},{"embedding":[0.020385,0.001076,0.016467,0.020484,0.009386,0.011881,0.068904,0.034327,-0.066895,0.029448,-0.016589,-0.035589,-0.003462,0.035295,0.018451,-0.040027,-0.054886,-0.125096,-0.003352,-0.034944,0.013849,-0.020108,-0.038928,-0.032873,0.084784,0.001441,0.043214,0.029655,0.023414,0.037095,0.04695,0.036419,0.004354,0.031542,-0.026983,-0.025394,0.027541,0.009016,0.068231,-0.029493,0.000883,-0.027152,-0.051917,-0.062689,0.105272,-0.062654,0.015358,0.08506,0.02853,0.015863,-0.027476,0.013137,-0.027288,0.046085,-0.072897,-0.010512,-0.056358,0.03125,0.068335,-0.035732,0.012376,0.010534,0.002982,0.016553,0.005128,-0.014716,-0.013111,0.007316,0.002888,0.05882,0.01215,-0.034134,-0.091507,0.004212,-0.007594,-0.037995,0.028933,-0.030376,0.038169,-0.003205,0.022947,0.005734,-0.065012,0.073394,-0.070999,0.057286,-0.019977,-0.00596,0.021413,-0.081416,0.076507,-0.002235,-0.057656,0.084215,-0.05599,-0.075392,0.003861,0.030991,-0.09011,0.056865,0.018066,-0.03808,0.00811,0.009905,-0.039035,0.065793,0.039115,0.078493,0.09474,0.01479,-0.102653,0.035977,-0.07933,0.011196,-0.015117,0.03025,-0.036907,0.006578,0.047466,0.054796,0.109018,0.049539,-0.056068,0.014254,-0.043373,-0.097752,0.029299,0.0,0.044912,0.082901,0.040984,0.042014,-0.049785,0.029435,0.063582,0.064793,-0.01197,-0.03921,0.036875,0.031493,-0.014887,-0.014325,0.004609,-0.023896,-0.012561,0.027701,0.090432,0.030129,0.04678,-0.041013,-0.027559,-0.007377,0.071247,0.03346,0.082149,-0.091312,0.101973,0.001107,0.061894,0.056996,0.01448,-0.05114,-0.038445,-0.03092,-0.045312,-0.093798,-0.015691,0.037766,-0.092393,0.066278,-0.012867,-0.07646,0.021234,0.049422,0.057941,0.073173,-0.05342,0.044521,-0.106493,0.025044,-0.082557,0.001202,-0.028568,-0.033082,0.014854,-0.033071,0.023693,-0.046173,0.00554,-0.107737,-0.076019,0.033354,-0.051851,-0.010242,-0.010046,-0.001687,-0.011626,0.069757,-0.008482,0.013809,0.000604,-0.004145,-0.08842,0.037715,-0.050393,0.048732,-0.012174,0.07673,0.082341,0.062292,0.020141,-0.04672,0.148805,0.080636,0.025018,-0.074989,-0.025787,0.01839,-0.035457,0.007783,0.081109,0.012059,-0.080392,-0.0,-0.077435,-0.018182,-0.058448,0.047181,0.040467,0.01957,0.051648,0.111443,0.029611,0.123661,-0.000938,0.009184,0.070841,0.012846,-0.037687,-0.062999,-0.008846,0.000451,-0.080176,-0.011739,0.006914,0.070057,0.007742,0.104363,0.077148,-0.002345,-0.021335,0.156574,-0.049214,-0.012746,-0.030114,-0.010601,-0.083196,-0.072366,-0.042441,0.000464,0.027171,-0.034169,0.033604,-0.00401,0.047977,-0.026446,-0.024889,-0.083481,-0.025028,-0.069348,0.045952,0.005779,-0.026165,-0.057804,0.085034,-0.002268,0.017414,-0.029107,0.01266,-0.024956,0.013614,0.009453,-0.052749,-0.02916,0.013244,0.069738,0.044456,0.110447,0.026732,-0.046563,0.068436,-0.00606,-0.001005,-0.088211,0.035495,-0.062896,0.003849,-0.039859,-0.040977,0.025065,-0.035199,-0.044936,0.037948,0.048223,0.018852,-0.003352,0.097959,-0.019405,-0.004048,0.008765,-0.011236,-0.049052,-0.00833,-0.027139,-0.108456,0.004253,-0.013205,0.084294,0.08864,-0.0,0.019143,-0.076079,0.014353,-0.022473,-0.058196,-0.077527,-0.036119,-0.005501,0.088459,-0.045641,-0.050914,-0.093315,-0.041881,0.046176,-0.048577,-0.081356,0.08692,0.020326,-0.015664,-0.046072,0.088758,-0.008317,0.034725,-0.001309,0.00581,-0.032414,0.044897,0.084635,-0.013401,0.025552,-0.105283,-0.089614,-0.009341,-0.036267,-0.040926,-0.044077,0.041405,-0.003198,-0.063466,0.000121,0.072344,-0.017784,0.004647,-0.046563,-0.088949,-0.027426,-0.06358,-0.087311,0.044802,-0.096058,-0.004402,-0.003683,0.052026,-0.093589,-0.036794,-0.021697,-0.026575,0.03535,-0.083812,0.094592,0.033471,-0.079165,-0.036589,0.056098],"category":"Investment Fraud","source":"seed_minilm"},{"embedding":[-0.080226,-0.009328,0.003719,0.015874,-0.003588,-0.025925,0.053978,0.046406,-0.066938,-0.014131,-0.051787,-0.051611,-0.032774,0.061145,0.016644,-0.032865,0.079327,-0.079933,0.030334,-0.098291,0.020045,-0.012041,0.030128,-0.039609,0.048876,-0.030068,0.026127,0.040518,0.049809,-0.036117,-0.00542,0.062349,-0.026429,0.038898,-0.047629,0.06466,-0.010958,-0.026365,0.054501,-0.03973,-0.010016,-0.03143,-0.086592,-0.047394,0.051183,-0.017971,0.059131,0.055002,0.003617,0.020581,-0.043821,0.017894,-0.014291,0.025007,-0.026405,-0.018718,-0.004366,0.032026,0.080166,-0.060771,0.01978,-0.000112,-0.037995,0.041678,0.019441,-0.041138,-0.037753,0.06429,-0.019677,-0.032185,0.002225,-0.016268,-0.093079,0.029292,-0.054034,-0.053347,0.080262,-0.049618,-0.050784,0.012695,-0.018423,-0.014266,-0.074412,-0.025408,-0.074722,0.039517,0.013357,0.06432,0.026711,-0.005027,0.036867,0.043705,0.000765,0.006699,0.010108,-0.08872,-0.020764,0.028106,-0.002503,0.034664,0.003896,-0.046458,0.01553,0.016238,-0.036444,0.060084,0.00419,0.072139,0.08544,0.027496,-0.102432,0.063732,-0.057769,-0.024782,0.011572,0.032654,-0.0162,0.070866,0.055962,0.074816,0.092135,0.079162,-0.050265,-0.035054,-0.020908,-0.059875,0.061258,0.0,0.099499,0.062205,-0.012541,0.01566,0.021324,0.096501,0.020926,0.051624,0.018475,-0.026708,-0.034386,-0.046213,-0.015549,0.017048,0.003125,-0.058908,0.014175,0.018068,0.023984,0.016342,0.027429,-0.014087,-0.009432,0.074178,0.017106,0.051174,0.051955,-0.089474,0.121885,0.02459,0.024571,0.024221,-0.010945,-0.025037,0.024724,-0.027974,-0.059765,-0.062575,-0.007144,0.016328,-0.046501,0.02146,0.003079,-0.067254,-0.077173,-0.005444,0.057736,0.046345,0.053975,0.094057,-0.00533,-0.000548,-0.009879,-0.07189,-0.026268,0.016499,0.002407,-0.056133,0.020762,-0.010351,-0.036074,-0.058527,-0.048373,-0.016151,-0.097148,-0.004298,0.05804,-0.000183,0.118638,0.035024,-0.058735,0.048033,0.032618,0.037009,-0.132581,0.041431,0.008842,-0.031388,-0.000895,0.113032,-0.028234,0.021576,0.087354,-0.075738,0.199106,0.077367,0.020467,-0.078631,0.064663,0.03494,-0.062892,0.016179,0.024752,0.002893,-0.020364,-0.0,-0.051499,-0.025994,-0.045075,0.065496,-0.023876,0.042563,0.010074,0.071263,-0.001841,0.170042,-0.069708,-0.017466,0.012227,-0.019593,-0.081265,-0.086705,-0.013144,-0.036229,-0.069979,0.020216,-0.041127,0.001561,-0.004661,0.071858,0.112404,0.007641,-0.048864,0.059677,0.010188,0.002381,0.022671,-0.046696,-0.112636,-0.058856,-0.024531,-0.003149,0.059003,0.057888,0.079145,0.033004,0.06559,0.005941,-0.002795,-0.053917,-0.098112,-0.048351,0.033419,0.003102,-0.120558,-0.079891,0.102204,0.007715,0.01655,0.014179,0.016111,-0.078349,-0.006472,-0.001903,-0.042268,-0.036556,0.031011,0.004752,0.055268,0.113467,0.043207,-0.055495,0.071971,0.026293,-0.036181,-0.077814,0.120058,-0.015654,0.101912,-0.002852,-0.034745,0.003447,-0.054946,-0.017871,0.071703,0.042665,-0.009678,0.018825,0.072072,-0.029106,-0.057103,0.012505,0.0257,0.005048,-0.014774,-0.074645,-0.096965,-0.021445,-0.021019,0.064356,0.136434,-0.0,0.028309,-0.03174,-0.023933,-0.051554,-0.054715,-0.062715,-0.001907,-0.003709,0.086697,0.02335,-0.010259,-0.113916,-0.022345,-0.0285,0.018252,-0.021827,0.006985,0.055864,0.005985,-0.036301,0.085895,0.017811,0.018937,-0.03502,-0.032448,-0.021026,0.004788,0.089877,0.011488,-0.056655,-0.082896,-0.024002,-0.045533,-0.109792,0.001019,-0.048865,0.018082,-0.014567,-0.054307,0.077615,0.040661,-0.028859,0.065543,-0.025718,-0.015269,-0.008214,-0.061535,-0.021439,-0.000483,-0.072393,-0.040688,0.047641,0.002671,-0.061397,-0.021248,0.013799,0.008625,-0.060797,-0.055608,0.02667,0.05148,-0.034277,-0.048357,-0.019045],"category":"Investment Fraud","source":"seed_minilm"},{"embedding":[-0.04402,-0.088989,-0.022386,0.046311,-0.029145,-0.004245,0.038983,0.040057,0.022219,0.033821,0.013549,0.038514,-0.053704,-0.068542,0.016941,-0.027991,0.013853,-0.04597,-0.009105,-0.012671,-0.093382,-0.140966,0.085148,-0.016485,0.073916,-0.057153,-0.015324,0.080706,-0.034685,-0.051252,-0.00583,0.048183,-0.007599,-0.036165,-0.012964,0.034405,-0.074035,-0.034854,0.065569,0.02733,-0.073984,-0.054568,-0.074826,0.000628,0.02609,0.002094,0.023181,0.107186,0.087024,0.067208,-0.052974,0.036272,-0.055255,0.036596,-0.027278,0.073109,-0.111836,-0.013828,0.054715,-0.020232,0.07446,-0.020814,-0.068637,0.017561,0.038357,0.015537,-0.041492,0.131633,0.026425,-0.000429,0.049666,-0.024579,-0.056808,0.00776,-0.074604,-0.018354,-0.018978,-0.057913,0.043474,0.075795,-0.041158,-0.011767,-0.003005,-0.063153,-0.007944,0.041476,0.125894,-0.021487,0.08366,-0.008364,0.051244,0.028847,-0.023131,0.009547,0.001349,-0.004674,-0.060568,-0.035031,-0.066083,0.056319,0.056523,-0.029463,-0.007867,-0.025893,-0.038134,-0.01256,-0.009374,0.05559,0.070392,0.064176,-0.01597,0.048697,0.025868,0.017691,0.013714,-0.01742,-0.038806,-0.042211,0.050747,0.031964,0.09767,0.120366,0.005149,0.010873,-0.059346,0.016498,0.073177,0.0,-0.009024,0.087044,0.010678,-0.028468,-0.074945,0.100276,-0.02722,0.018066,-0.066005,-0.038611,-0.05662,-0.015712,-0.020889,-0.057767,-0.030912,-0.076381,-0.007753,0.044016,0.114304,-0.037896,0.033917,-0.008802,0.019638,-0.05525,-0.015642,-0.043316,0.017929,-0.029405,0.04957,0.031672,0.025759,0.096113,-0.001977,-0.080743,-0.003656,-0.007595,-0.00224,0.01358,-0.044859,0.008384,-0.103984,0.022357,-0.019171,-0.055875,-0.001547,-0.04451,0.020384,-0.028295,0.02573,-0.014809,-0.024453,0.006408,-0.054026,-0.000205,-0.001473,0.031071,-0.012263,-0.040525,-0.087943,0.010707,-0.00121,-0.044218,0.015684,-0.043157,-0.172574,0.064979,-0.008429,0.062768,-0.060893,0.17432,-0.012343,0.001788,-0.000446,0.025607,-0.063302,-0.012055,-0.030192,-0.004506,0.034606,0.025074,0.030023,-0.056127,0.053954,0.004648,0.082684,0.006792,0.063312,-0.098321,0.064037,0.003539,-0.007427,-0.04816,0.050315,0.09772,-0.013179,-0.0,-0.035071,0.01528,0.02913,0.09097,-0.059269,0.000287,-0.01235,0.053534,-0.000128,0.115914,-0.044216,0.011006,0.023958,0.032912,-0.006198,-0.095793,0.016729,-0.01813,-0.029405,-0.001256,0.006511,-0.021426,-0.122284,0.087933,0.002739,0.071443,-0.06515,0.0534,0.011069,-0.030275,-0.013319,-0.018477,-0.021472,-0.065676,0.030585,0.024359,0.087878,-0.002414,0.056482,0.03468,0.091128,-0.055014,-0.034641,-0.044965,0.01828,0.012506,0.060847,0.012447,-0.017735,0.002658,0.077964,-0.083605,-0.004352,0.025438,-0.0483,-0.046019,-0.000219,-0.015866,-0.013392,0.025638,-0.027272,-0.004829,0.04601,0.010505,0.054923,-0.014463,-0.034866,0.00593,0.035393,-0.004257,0.087335,-0.000462,-0.046246,-0.107185,0.038603,0.084495,0.00704,-0.007822,0.010324,0.088303,-0.001185,0.072996,-0.039009,0.026247,-0.003586,0.035583,0.032956,-0.062664,-0.061116,0.053502,-0.04691,-0.083269,-0.011158,0.062183,0.04484,-0.0,-0.020447,-0.029351,0.069991,0.031507,-0.002801,-0.011905,0.034625,-0.05291,0.002785,-0.038446,0.064666,-0.025716,-0.074084,-0.007238,-0.047873,-0.054759,-0.099916,0.029215,-0.059427,-0.079302,0.089032,0.084118,0.103341,0.02095,-0.02154,-0.036038,0.076966,0.168133,-0.03381,-0.009186,-0.054471,-0.096514,0.08247,-0.065912,-0.047351,0.031253,0.06944,-0.006953,0.022294,-0.025018,0.053774,-0.021229,0.02579,-0.032274,-0.04301,-0.027821,-0.02465,-0.006017,0.045105,-0.077474,-0.014032,-0.001764,0.017009,0.052336,0.00234,0.054854,-0.055762,0.015545,-0.077207,-0.027634,0.004749,-0.062766,-0.052456,5.2e-05],"category":"Investment Fraud","source":"seed_minilm"},{"embedding":[-0.003915,-0.013413,-0.060673,0.068409,-0.02536,-0.054523,0.033534,0.064856,-0.022736,-0.023001,-0.018403,-0.095799,-0.012962,0.044507,0.07701,0.016012,0.000716,-0.006495,-0.016489,-0.057505,-0.001469,-0.07444,0.03031,-0.031927,0.028745,-0.033079,0.064036,0.042985,0.024342,-0.026454,0.02454,-0.001423,0.048503,0.011892,-0.003202,0.015916,-0.073712,0.014032,0.038125,-0.024365,0.028556,-0.052924,-0.060145,-0.030289,-0.025917,0.013783,0.01212,0.11154,0.082815,-0.009966,-0.086897,-0.019549,0.007949,0.01522,-0.144915,0.001063,-0.002485,-0.021512,0.09427,-0.105022,0.065991,0.02512,0.043891,0.046562,0.04851,-0.034483,-0.053612,0.004939,-0.051297,0.034585,0.047474,-0.034911,-0.098247,0.037367,-0.037544,-0.051752,0.058663,-0.051126,0.038701,0.024972,-0.025133,-0.01455,-0.029799,0.010102,-0.030521,0.1353,0.055641,0.030534,0.041819,0.013435,0.088875,0.012105,-0.026976,-0.001196,-0.016497,0.002301,-0.003928,0.055914,-0.045275,0.02662,0.023534,-0.062228,-0.090017,-0.050605,0.045697,0.031068,0.023793,0.001375,0.07653,0.03557,-0.078821,0.025033,-0.022176,0.006346,-0.000799,0.119513,-0.023417,0.046821,0.00036,0.107456,0.08876,0.034797,-0.018178,-0.053388,-0.006617,-0.062155,0.073804,0.0,-0.054359,-0.026559,-0.01349,-0.028821,-0.035921,0.053695,0.040715,-0.01033,-0.036093,-0.033822,-0.062925,0.004635,-0.010015,0.039036,-0.031413,-0.072199,0.057045,-0.011121,0.106657,-0.053734,0.082747,-0.056076,0.032075,0.062797,-0.002009,0.125174,0.02244,-0.079837,0.099299,0.031709,0.016757,0.034178,-0.106925,-0.002628,-0.018724,0.040594,0.031373,-0.032017,-0.062607,0.010742,-0.097329,0.001702,-0.048221,-0.06867,-0.037791,0.027256,0.030663,-0.007116,0.044638,0.04458,-0.087441,0.007677,-0.076412,-0.034842,0.018537,-0.112366,-0.000241,-0.047632,-0.034109,-0.033412,0.007846,-0.014366,-0.017159,-0.014488,-0.095668,0.026657,0.009869,-0.013533,-0.041231,0.101644,0.037584,0.016329,0.103733,0.042191,-0.05177,0.000171,-0.023712,-0.015268,0.035218,0.067479,0.03195,0.004809,0.023374,-0.023191,0.08415,0.054955,-0.019218,-0.023407,0.004079,-0.007139,-0.058065,-0.016241,-0.008997,0.024679,-0.058455,-0.0,-0.082144,0.019082,-0.009743,0.108826,-0.021167,-0.007821,-0.03417,0.080344,0.070633,0.127965,-0.053287,-0.001807,0.105164,0.010621,0.047092,-0.082882,-0.002699,0.079655,-0.014145,-0.040107,-0.028481,0.077308,-0.080856,0.042867,0.125592,0.007696,-0.047549,0.084121,0.018148,-0.01769,-0.007115,0.074961,-0.018913,-0.057013,-0.01808,-0.012633,0.025799,-0.037921,0.048033,0.008883,0.067112,0.013445,0.016469,-0.061782,-0.034774,-0.091833,0.010978,0.006887,0.08841,-0.000118,0.051168,0.005378,0.013691,-0.028125,-0.048859,0.061548,-0.055186,0.062953,-0.003045,-0.012227,-0.032341,0.023866,0.011108,0.098353,0.036337,0.008302,-0.005937,0.073487,0.026776,-0.083667,0.094452,-0.018467,0.023656,-0.060786,-0.020913,0.007974,-0.042215,0.009606,0.076815,0.033653,0.012427,0.049599,0.065134,0.012534,-0.050712,-0.002823,0.001748,0.007752,-0.022533,-0.033695,-0.082123,-0.047999,0.02672,0.095059,0.019275,-0.0,0.012865,-0.080013,0.102785,0.047361,0.05608,0.056115,-0.017891,-0.066733,-0.027485,0.04042,0.021038,-0.06966,-0.07454,0.037286,-0.005832,-0.022843,-0.040061,0.050012,0.017123,-0.101623,0.109888,-0.034597,0.035797,-0.024028,-0.033551,-0.010844,0.031681,0.054025,-0.059765,-0.012945,-0.125053,-0.035552,0.064936,-0.031463,-0.026461,0.051268,-0.052049,-0.020748,-0.048905,0.052536,-0.067228,-0.042618,0.081433,-0.061398,-0.091644,0.022787,-0.041553,-0.088621,0.04643,-0.110011,-0.016375,-0.039012,0.051303,-0.013873,-0.002282,0.04429,-0.030454,-0.054781,-0.079774,-0.050786,0.0017,-0.030928,-0.033364,-0.023872],"category":"Investment Fraud","source":"seed_minilm"},{"embedding":[0.025652,0.047671,-0.017806,0.016834,0.006062,-0.027197,-0.00254,0.095724,-0.063544,-0.023674,0.040952,-0.027121,0.010499,-0.04355,0.046781,-0.004184,-0.029612,0.001174,-0.004164,0.005504,0.019119,-0.011285,-0.047263,-0.024259,0.047591,-0.074201,0.046538,0.023444,-0.066011,-0.023275,0.158642,0.107685,-0.004745,-0.019555,-0.036472,0.008406,-0.01478,-0.020935,-0.014032,0.01416,-0.032813,-0.040645,-0.019561,-0.064365,-0.006249,-0.05833,0.017186,0.05133,0.029109,0.048307,-0.066643,0.034596,-0.040458,0.03052,-0.019393,0.003354,-0.000134,-0.018522,-0.038773,-0.038859,0.029799,0.018403,0.008551,-0.0211,0.044426,0.010886,-0.064313,-0.031134,-0.023236,0.03155,0.07999,-0.067972,-0.099097,-0.059927,-0.071901,0.048471,-0.024373,0.018404,0.051973,-0.031176,0.004897,-0.004928,0.055786,-0.07452,-0.011807,0.032381,0.04732,-0.001175,0.019162,0.019272,0.131014,0.000408,-0.000868,0.032021,-0.068664,-0.009468,-0.065841,-0.018881,-0.04473,0.055498,-0.022039,0.05393,-0.066869,-0.034619,-0.064716,0.010408,0.086642,0.06435,-0.014069,-0.079513,0.006896,0.084141,0.022251,0.055454,-0.021548,0.096014,-0.02844,0.083342,0.049821,0.042741,0.063009,0.052129,0.011246,0.033853,-0.020718,-0.046664,-0.035513,0.0,-0.022392,0.085084,-0.001223,-0.068413,-0.076747,-0.00866,0.013002,0.007911,-0.111507,-0.034248,0.007651,-0.024795,0.023713,0.001585,-0.023097,-0.076559,-0.003221,0.053211,0.113244,-0.02967,0.125103,-0.076089,0.04858,0.007236,0.043709,-0.006792,-0.002411,0.010591,0.060884,0.043076,0.044693,0.057304,-0.021686,-0.074809,0.026354,0.02379,0.076086,-0.014657,-0.115665,-0.029111,-0.030142,0.05709,-0.022814,-0.046884,-0.008328,-0.000576,0.006221,0.077092,0.049807,0.070242,-0.077379,0.006381,-0.032063,-0.020883,-0.000778,-0.09426,-0.044555,-0.026644,0.001999,0.0611,0.076154,-0.100603,-0.094221,-0.015263,-0.130401,0.068845,0.065661,-0.032435,0.038,0.018589,0.005313,0.051961,0.068242,-0.005296,-0.020163,-0.087258,0.022815,-0.018507,0.081581,0.027693,0.014464,-0.010169,-0.084728,-0.059699,0.14966,0.033064,0.00203,-0.002278,-0.015666,-0.067782,0.004621,-0.05523,0.066834,-0.020366,0.034339,-0.0,-0.058834,-0.034874,-0.011501,0.024766,0.041565,0.012108,0.045426,0.054242,-0.020218,0.062162,-0.000815,-0.025321,0.053214,-0.039003,-0.027084,-0.068071,0.047601,-0.09718,-0.022862,-0.003935,-0.002132,0.078694,0.086145,0.092652,0.068718,0.106633,-0.058066,0.030335,-0.042162,0.041334,0.006642,-0.024124,-0.11669,0.021658,-0.037479,-0.035647,-0.001965,-0.048526,0.023968,0.014383,0.003104,0.061988,0.007113,-0.01934,-0.015946,-0.013229,0.008421,0.041311,0.072005,-0.063981,0.01078,0.012184,0.029165,-0.01261,-0.01858,0.020609,0.066829,0.003289,-0.110695,-0.003859,0.020934,0.041588,0.018407,0.06908,0.053695,-0.032861,0.059844,0.020645,0.074879,-0.052177,0.031354,0.011906,-0.008564,0.013937,-0.007914,0.028988,0.000245,0.055127,0.027044,0.128837,-0.017896,0.034203,0.040566,0.032052,0.041093,-0.048692,-0.058573,-0.054349,0.039563,0.045142,-0.082123,0.023677,0.051592,0.10115,0.116972,-0.0,-0.00343,-0.102539,0.018922,0.034373,0.107382,-0.084511,-0.108562,-0.037079,-0.029783,-0.061631,-0.032648,0.018275,-0.088967,0.012077,0.00695,-0.10104,0.055894,0.068722,-0.055898,-0.048509,0.010651,0.041048,0.030973,0.01032,-0.046384,0.019372,0.016028,0.020282,0.048397,0.009105,0.000631,-0.087527,-0.000167,-0.026451,-0.095194,-0.003284,0.041501,0.055642,0.016999,0.040869,-0.012594,-0.067502,0.061685,-0.014476,-0.038899,-0.057696,-0.089468,-0.058117,-0.048918,-0.116918,0.030275,-0.008764,-0.008582,0.057281,-0.009475,0.06058,-0.068204,-0.015181,-0.060536,0.033029,-0.006918,-0.100642,-0.079524,-0.021964],"category":"Investment Fraud","source":"seed_minilm"},{"embedding":[-0.05323,-0.067046,0.013672,0.004812,-0.050088,0.018788,-0.024585,-0.025925,-0.141763,-0.091569,-0.054877,-0.102057,0.013088,-0.060629,-0.012205,-0.009808,0.025429,-0.088442,0.017029,-0.020641,0.042397,0.055932,-0.052208,-0.053849,0.108127,-0.02522,0.077416,0.05435,0.053059,0.040513,0.048967,0.082798,0.014608,0.044524,0.030096,0.052514,-0.038125,0.087869,0.013721,0.031924,-0.00744,-0.035338,-0.053727,-0.022821,0.058128,0.017496,0.00195,0.001999,0.015824,0.012165,-0.045377,0.025852,0.003596,0.063604,-0.045514,-0.004281,0.030609,-0.006197,0.004425,-0.039289,0.02099,0.089794,-0.021065,0.003789,-0.004443,-0.029141,-0.064061,0.027133,0.05923,-0.062333,-0.005027,-0.007784,-0.070038,0.026418,0.00262,0.059917,0.013443,-0.045774,0.066036,0.006045,-0.076862,-0.05899,-0.061923,0.090803,-0.070595,0.019233,-0.005243,0.043627,0.011195,-0.03289,0.108749,-0.015613,-0.049281,-0.030442,-0.063573,-0.063812,-0.026343,-0.049066,0.006681,0.003428,-0.033898,-0.006695,-0.066002,0.087395,-0.05995,0.027076,0.038825,0.05364,-0.01403,-0.008143,-0.03619,0.008627,-0.085015,-0.024238,-0.017051,0.016537,0.018835,-8.1e-05,0.019581,0.042971,-0.011396,0.105681,-0.050064,-0.052415,0.04847,-0.096358,0.066146,0.0,0.071436,0.038879,0.12239,0.002906,0.034466,0.027019,0.004022,0.059586,0.116388,0.080183,-0.000321,0.00477,0.017378,-0.120716,-0.066608,0.028406,-0.007174,0.023577,0.001613,0.086492,0.055027,-0.037767,-0.042857,0.063011,-0.008815,0.023844,0.061159,-0.023104,0.088173,0.007464,0.052555,-0.062728,-0.007686,-0.043481,-0.036619,0.017519,0.003195,-0.115899,-0.07302,-0.031199,-0.039072,0.010927,0.096333,-0.034794,-0.004929,-0.010811,0.068854,0.038168,0.018629,0.097829,-0.026296,0.011384,-0.031319,0.08028,-0.022292,-0.016194,0.015559,-0.013734,0.033751,0.011945,0.049588,-0.045292,-0.037642,0.004272,-0.018627,-0.060211,0.058095,-0.091774,0.065087,0.029483,0.011687,0.028619,0.07133,0.018305,-0.004145,0.055804,-0.033037,-0.026727,0.030286,0.038719,0.020311,0.050589,0.009486,-0.004745,0.227954,0.063161,-0.023285,-0.0235,-0.004448,0.007386,-0.032065,0.053764,0.048641,-0.01776,-0.05029,-0.0,-0.103256,-0.063148,-0.044325,0.036342,0.043207,0.033194,-0.030939,0.071848,0.062321,0.050067,0.037464,0.04961,0.05847,-0.034646,-0.045426,-0.047593,-0.047309,0.049575,-0.032344,0.030129,-0.010715,0.067999,0.0175,0.063232,0.113094,-0.016068,0.03148,0.168834,0.009766,-0.01679,-0.020979,-0.02407,-0.102385,0.026396,-0.041866,-0.044171,0.056153,0.025864,-0.023906,0.005396,-0.024173,0.010588,-0.027458,-0.068614,-0.0914,-0.09788,0.05592,0.009367,0.018274,-0.036573,0.063274,0.037917,-0.013552,0.040065,0.030871,0.006766,0.074799,-0.031624,-0.03705,0.002363,0.067873,0.070781,0.014066,0.089533,0.059112,0.00023,-0.015169,-0.03833,-0.008749,-0.098288,-0.003033,-0.004296,0.080464,0.046812,-0.029968,0.001456,-0.036659,-0.028766,0.063321,0.053486,0.017103,-0.041784,0.055765,0.005121,-0.017856,-0.007621,-0.028435,0.025646,0.028745,-0.029526,-0.11519,-0.013788,-0.020607,0.042795,0.017428,-0.0,0.084608,-0.06736,0.07579,-0.092901,-0.02546,-0.074068,-0.069508,0.014279,0.016247,-0.052528,-0.015379,-0.024434,-0.045534,-0.006596,-0.00863,-0.045484,0.120855,0.000685,-0.027165,-0.007344,0.025826,-0.034127,-0.033079,-0.035179,-0.006802,0.054956,-0.026283,0.065905,-0.042316,-0.04815,0.010313,-0.008212,0.022635,-0.045858,-0.092742,-0.001324,0.025688,-0.011684,-0.081615,-0.037609,-0.07681,-0.033059,-0.019869,-0.078371,-0.024184,0.019848,-0.020457,-0.064613,0.031001,-0.043567,-0.010033,-0.037797,0.063292,-0.08836,-0.022503,-0.00547,-0.048077,-0.083518,-0.006668,0.140865,0.013535,-0.031537,-0.044503,-0.000951],"category":"Investment Fraud","source":"seed_minilm"},{"embedding":[0.026381,-0.054033,-0.086128,0.030024,0.030089,-0.069245,0.029338,0.061096,-0.0228,0.030427,-0.029327,0.006329,-0.116961,0.055676,0.023441,0.038489,0.031061,-0.019512,0.026401,-0.011693,0.052106,-0.083321,0.011784,-0.053578,0.075126,0.043756,-0.033096,-0.008446,-0.085165,-0.032337,0.009926,0.059004,0.048556,-0.059823,-0.088493,-0.028386,-0.018112,0.036189,0.058609,-0.042528,-0.048441,0.018634,-0.007909,-0.062966,0.003482,-0.034358,-0.049422,0.100169,-0.017007,0.056445,0.00944,0.019784,0.004663,0.027215,0.016366,-0.00732,-0.055753,-0.050555,0.079382,-0.079258,0.083249,0.014571,-0.003025,0.024044,0.003592,-0.029153,-0.040379,0.031209,-0.001488,-0.060443,0.039039,-0.023978,-0.093441,-0.048349,-0.075315,0.06787,0.081166,0.067628,0.100485,-0.027153,0.033444,0.032274,0.036387,-0.022741,0.052742,0.01181,0.053947,0.029459,0.006518,-0.064162,0.087495,0.051583,-0.005146,0.052707,-0.048583,-0.053342,0.022957,-0.067298,-0.017846,0.061395,0.089011,0.036243,-0.003976,-0.044484,-0.065359,-0.043265,0.018049,0.075492,0.054091,-0.009002,-0.026306,0.089633,-0.038838,0.008726,-0.076666,0.102351,-0.188958,0.014858,0.06736,0.096511,0.033406,0.051192,-0.025543,0.03027,-0.030803,-0.086531,-0.011191,0.0,-0.088299,0.048281,-0.00098,-0.116044,-0.030401,-0.040121,0.001431,0.01954,0.001513,-0.005571,-0.004092,0.034904,0.038379,0.022796,-0.022977,-0.061121,0.010558,0.056497,0.107694,0.016178,-0.022327,0.00095,-0.020134,0.033411,0.023983,0.02886,-0.018354,-0.007425,0.107058,0.072972,0.058408,-0.001949,-0.038556,-0.075154,0.027047,0.055871,0.063823,-0.048704,-0.050858,-0.031039,0.024174,0.009838,-0.060651,0.078293,-0.043533,0.020614,0.018336,0.078809,-0.006033,0.091376,-0.081503,0.021816,-0.102159,-0.017763,0.003518,0.009779,-0.046352,-0.018165,0.025909,-0.031964,0.045925,-0.071168,-0.110066,-0.050622,-0.153241,0.10268,0.040575,-0.109466,-0.007502,0.080897,0.004996,-0.016205,0.018819,0.039447,-0.049634,-0.017307,0.017951,0.013,0.038731,0.024472,-0.036516,-0.00182,-0.082051,-0.057763,0.055805,0.05372,0.013861,0.008084,0.008056,-0.006739,0.029028,-0.096286,0.040914,0.010182,0.020914,-0.0,-0.091802,0.045356,0.000491,0.062028,-0.021541,-0.019149,-0.039182,0.066013,0.067354,0.065612,0.012305,0.012545,-0.020587,0.064494,0.022178,-0.047754,-0.011799,0.026411,-0.040877,-0.026592,0.060716,0.012039,0.028884,0.076864,0.014571,0.110099,-0.061469,-0.030464,-0.007933,-0.048898,0.00502,-0.014157,-0.103653,-0.00419,-0.033184,-0.048759,0.035263,-0.00978,0.021279,0.061428,0.042948,0.046142,-0.003676,0.054121,-0.039042,0.020258,0.040434,0.122754,0.141191,-0.032808,-0.019865,-0.015872,-0.003808,-0.024309,-0.060159,0.073382,0.059226,0.012214,-0.026499,-0.010905,0.011489,0.026021,0.056332,0.027709,-0.003294,-0.034451,0.031489,0.008642,0.024883,0.005592,0.00528,-0.015918,0.021014,-0.019931,0.002951,0.036773,-0.008584,-0.037306,0.032525,0.023738,0.00543,0.077001,0.074546,-0.059262,0.048671,-0.00825,0.005291,-0.070442,-0.03855,0.029234,-0.058772,-0.02478,0.026227,0.043256,0.008692,-0.0,0.03732,-0.082435,0.034894,-0.018368,0.07176,0.036621,-0.003512,-0.016278,-0.036537,-0.066111,0.014211,0.010606,-0.131384,-0.045037,-0.017592,-0.079096,0.045719,0.004335,-0.032717,-0.054334,0.116296,0.010833,0.108264,-0.029487,0.03602,0.015542,0.065711,0.056037,-0.046027,-0.035095,-0.03534,0.043504,0.036988,-0.026879,-0.042836,0.004052,0.076036,0.022705,0.014166,-0.048704,-0.051234,-0.080486,-0.013977,-0.038336,-0.026335,-0.0224,-0.028676,-0.023195,0.031974,-0.076565,-0.103114,-0.07223,-0.036506,-0.027456,-0.028001,-0.014573,-0.108643,0.035339,-0.096477,-0.010347,0.010304,-0.097418,-0.034029,0.022632],"category":"Investment Fraud","source":"seed_minilm"},{"embedding":[-0.02247,-0.091259,-0.035256,0.076928,-0.011561,0.009546,0.00423,-0.023505,-0.084675,-0.043289,-0.003432,-0.084599,0.024311,-0.010553,0.027016,0.101808,0.080204,0.032507,0.044822,-0.075458,-0.04354,-0.022096,-0.041116,-0.055327,0.036768,-0.077195,0.092457,0.045425,0.021887,-0.042091,0.061891,0.064683,0.033098,0.057174,0.037986,0.002599,-0.052593,-0.050596,0.056355,0.002448,0.040521,-0.027974,-0.032874,-0.119132,0.040556,-0.020265,-0.01951,0.057449,0.032105,-0.007528,-0.081527,-0.116812,-0.018331,0.054758,-0.077689,-0.027365,-0.021228,0.014451,-0.002679,-0.042978,0.006273,0.043813,-0.031139,-0.005926,0.065108,-0.030915,-0.040619,0.100995,-0.019375,-0.020151,0.023318,-0.058379,-0.168534,-0.009844,0.019619,0.043961,0.079079,-0.060994,0.038908,0.011833,-0.018344,0.035129,-0.097961,0.046049,-0.097523,-0.002926,-0.011622,0.007059,0.034781,0.032895,0.009186,0.05767,-0.102167,0.022322,-0.005884,0.003815,-0.034981,0.023044,0.002145,0.05972,-0.047165,-0.020884,-0.080501,-0.06677,-0.072877,-0.004246,0.065357,0.090581,0.075758,0.038203,-0.025167,-0.013408,-0.053412,-0.01436,-0.009783,0.022725,-0.010639,0.016147,0.032017,0.103063,0.007447,0.104379,-0.00915,-0.062277,0.024382,-0.053505,-0.000702,0.0,-0.024613,0.033491,0.046838,0.042524,0.055548,0.008962,0.088951,-0.008466,0.013553,-0.039466,-0.025149,0.055263,0.016167,-0.005287,-0.041371,-0.089927,0.080628,0.002808,0.02599,0.015244,0.008178,-0.039024,-0.016429,-0.00237,0.003965,-0.022905,-0.02906,-0.018874,0.11678,0.030179,0.002799,0.051459,-0.027717,-0.03763,-0.029024,0.087008,-0.006655,-0.095973,-0.013779,0.029144,-0.138597,0.034866,0.058114,-0.051618,-0.063812,0.048836,0.019727,0.016374,0.027406,0.055554,-0.014092,-0.001001,-0.005961,-0.015608,0.022576,-0.005597,-0.008818,0.05344,0.001399,-0.004979,-0.012868,-0.014683,0.000885,0.058321,-0.029867,-0.019994,0.02312,-0.001824,0.156244,0.021138,0.012631,0.014845,0.038344,0.015363,-0.074415,-0.013169,-0.071308,-0.014665,0.083161,0.064535,0.066022,0.074873,-0.043158,0.014149,0.160448,0.012445,0.05387,-0.075379,0.033419,0.025799,-0.017353,0.062498,0.005778,0.075895,-0.010519,-0.0,-0.018853,0.085357,-0.022705,0.058923,0.038507,0.065461,-0.012339,-0.009948,0.022816,0.182569,0.00093,-0.061033,0.050657,0.017377,0.002535,-0.155591,-0.003917,0.027975,-0.006888,0.047536,0.03424,0.086039,-0.057124,0.026351,0.063595,0.052773,-0.081611,0.116059,-0.078508,0.031648,-0.013503,0.021448,-0.040573,-0.041042,-0.020778,0.020458,0.077493,-0.017124,0.023322,0.031961,0.012382,-0.075944,-0.028946,-0.080828,-0.071674,-0.032977,0.103298,-0.021868,0.019359,-0.067621,-0.025799,-0.008533,-0.00201,0.057761,-0.029986,-0.016159,-0.010603,0.002609,0.04141,0.03431,0.04838,0.042646,0.043498,0.062771,0.0323,-0.034569,0.107939,0.002688,-0.061739,-0.054534,0.004833,0.029398,0.070964,-0.041827,-0.108711,0.003738,-0.091396,0.034503,0.021328,-0.024042,-0.040502,-0.032316,0.005645,-0.003118,0.067064,-0.009276,0.015991,-0.023451,0.002808,-0.07665,-0.070254,-0.063642,0.03784,0.028522,0.013365,-0.0,0.016652,-0.016784,-0.005173,0.006145,0.018988,-0.014362,-0.093628,0.018395,0.053862,0.068856,0.001743,-0.132733,-0.039275,0.03964,0.029565,-0.022891,0.006178,-0.013171,-0.039921,-0.041477,0.056391,0.008141,0.002261,-0.064882,0.012276,-0.00823,-0.047492,0.082435,-0.041329,0.014642,-0.067617,-0.033503,-0.021497,-0.029421,-0.066422,-0.013739,-0.029574,0.023936,-0.065773,0.039377,-0.023588,-0.024813,-0.011643,-0.060356,0.022716,0.051284,-0.038695,-0.021465,6.2e-05,-0.05653,-0.004209,-0.036275,0.071615,-0.042259,0.028713,-0.027459,-0.013998,0.048165,-0.077521,0.045059,0.028933,-0.07661,-0.11391,-0.044564],"category":"Investment Fraud","source":"seed_minilm"},{"embedding":[-0.040379,-0.049914,-0.037332,0.004476,-0.046203,-0.085607,0.001427,0.031315,0.00863,-0.055609,0.004829,-0.019109,0.019605,-0.001834,0.053805,-0.05044,0.039095,0.02304,0.03629,-0.011484,-0.046794,-0.087612,0.005153,-0.035462,0.069362,0.014893,0.047173,0.010266,-0.008496,-0.047036,-0.022196,0.047478,-0.006817,0.021485,-0.024653,0.031473,-0.059245,0.00746,0.014791,-0.071373,0.018975,-0.052661,0.049626,-0.038935,-0.012135,0.022845,0.024845,0.039189,0.075632,0.008315,-0.064596,0.008144,0.042301,0.034833,-0.036019,0.027637,0.025858,-0.003171,0.049911,-0.041046,0.05849,0.020276,-0.021086,0.012026,0.01249,0.05289,-0.074561,0.01017,-0.027948,-0.024869,-0.019782,-0.014737,-0.037581,0.014987,-0.05104,-0.027479,0.072662,-0.057709,0.002444,-0.004329,-0.049303,-0.031993,-0.063194,-0.002776,0.044055,0.0667,0.104622,-0.006326,0.088143,-0.06823,0.03031,0.014204,0.021241,0.000111,-0.037928,-0.01946,-0.017163,0.014731,-0.033568,0.059296,0.07549,-0.031593,-0.059629,0.037012,-0.091116,-0.031367,-0.026458,0.025848,0.039364,-0.029313,-0.084801,-0.011764,0.032219,-0.024738,-0.068635,0.080027,-0.091389,0.041479,0.038076,0.031714,0.023524,-0.00654,-0.00822,0.072711,0.053595,-0.041,0.011302,0.0,-0.143284,0.07047,0.016621,-0.055788,-0.042816,0.067847,-0.022333,-0.021089,-0.014262,0.091901,-0.108125,0.075575,-0.054215,0.081943,0.034121,-0.062998,0.045186,0.006005,0.065148,-0.013765,0.036789,-0.068293,0.007395,-0.0313,-0.01079,0.055928,-0.062486,-0.005609,0.090757,0.025521,-0.043743,0.023697,-0.016064,0.033772,-0.065559,-0.027666,-0.043385,-0.0867,-0.063581,0.052613,-0.063955,0.025561,-0.018505,-0.082419,-0.049146,0.025361,0.02008,0.007578,0.03438,0.025791,-0.051091,0.034866,-0.036465,-0.048545,0.025004,-0.064961,0.052605,-0.029296,-0.058875,0.060416,0.021536,-0.012896,0.002433,-0.004104,-0.098718,0.08226,0.037505,-0.03627,-0.010284,0.096248,-0.08342,0.0831,0.076707,-0.01478,0.026595,-0.018124,-0.003612,0.028635,0.071808,-0.025031,-0.049757,-0.015273,0.028903,0.034116,0.113164,0.021308,-0.075173,-0.048201,-0.004373,0.002744,-0.05964,-0.02152,0.01993,0.051223,-0.069082,-0.0,-0.104646,0.040625,-0.015617,0.043488,-0.084874,0.022906,-0.006624,-0.016089,0.033573,0.07438,-0.034627,-0.016604,0.06403,0.029207,0.015512,-0.07274,0.061135,-0.020078,-0.013337,-0.088808,0.05953,0.03703,-0.073623,-0.000925,0.053316,0.00917,-0.00849,0.058646,-0.054302,0.05979,-0.086252,0.029994,0.020809,-0.011797,-0.017373,0.041937,0.055856,0.05747,0.065526,0.030055,-0.005122,0.045763,0.01505,-0.037883,-0.088152,-0.054717,-0.019685,0.086554,0.011583,0.060597,0.01312,0.088562,0.018904,-0.096283,-0.102908,0.099856,-0.013275,0.015431,0.020997,0.00526,-0.05861,-0.058345,0.0342,0.065855,0.056055,0.059442,0.052288,-0.013895,0.117455,-0.025069,0.131161,0.044767,-0.036504,-0.001707,0.044359,0.041215,-0.021203,-0.019209,0.038748,0.071962,0.031575,0.058335,0.081551,0.039177,-0.013927,0.123105,-0.044504,-0.055516,0.050659,-0.02721,-0.028506,0.051315,0.038021,0.045974,-0.056941,-0.0,-0.084888,-0.062534,-0.000255,0.007572,0.037081,0.050736,-0.021719,-0.096323,-0.05482,-0.075773,0.068175,-0.054058,-0.100786,0.014121,0.021934,-0.061786,0.04941,0.023205,-0.054243,-0.048932,0.133089,0.012862,0.065177,0.003984,0.000271,-0.056371,0.003189,0.135625,-0.037239,-0.010255,-0.04752,-0.055725,0.072783,-0.00836,0.009211,0.058532,-0.028265,0.024928,-0.030502,0.077975,-0.01211,-0.008435,-0.023384,-0.013035,0.015761,0.036438,-0.020119,-0.175516,0.069104,-0.12456,0.024173,-0.008618,0.016931,0.028886,0.085518,0.014773,-0.05766,-0.073389,-0.056135,0.055711,-0.024774,0.040096,-0.071059,-0.019375],"category":"Investment Fraud","source":"seed_minilm"},{"embedding":[-0.043141,0.05665,-0.1029,-0.041901,0.003446,-0.039771,0.070396,-0.036272,0.016843,-0.038803,0.049293,-0.059852,0.027621,-0.01478,-0.048639,0.066734,0.032465,-0.076505,-0.060331,-0.038498,-0.044193,0.077619,-0.036105,-0.03038,-0.000782,0.02827,0.011436,-0.007769,0.015945,0.039503,0.066562,0.092013,-0.038733,-0.00165,-0.003444,0.024154,-0.062104,0.025734,0.08782,-0.023351,0.064912,-0.043381,0.046747,-0.009462,0.038998,0.042801,-0.010177,0.045651,0.036771,0.039797,0.010812,-0.003779,-0.010576,0.092888,-0.04301,-0.068338,0.039073,0.061537,0.007237,-0.031497,-0.046516,0.097478,0.034624,0.013897,0.038762,-0.002059,-0.075398,-0.052602,0.075789,-0.05614,0.097134,-0.055816,-0.035494,0.007043,-0.043178,0.015,-0.001812,0.031601,-0.002751,-0.002872,-0.020029,-0.022408,0.060366,-0.007049,-0.008948,-0.012632,-0.010112,0.012226,-0.004428,0.042427,0.084973,0.053017,0.014356,0.005103,-0.035143,-0.051895,-0.000255,0.059286,-0.027128,0.027599,-0.032532,0.058051,-0.098212,0.020701,-7.1e-05,-0.054389,0.05455,0.029641,0.031144,0.000631,-0.013569,0.033643,-0.041474,-0.039818,-0.037136,0.05546,-0.09302,0.070875,-0.020017,-0.031063,-0.028547,0.105812,-0.078126,-0.040536,-0.040654,-0.084204,0.035912,0.0,-0.065169,0.009023,0.02405,-0.079672,0.020091,-0.046926,-0.026616,-0.015829,0.05397,0.028288,-0.003729,-0.013926,0.003081,-0.065094,-0.035577,-0.028158,0.069466,-0.039719,0.07281,0.064591,0.048568,-0.051956,-0.008623,-0.002351,-0.007357,0.043997,0.06397,-0.034781,0.044234,0.02911,0.026204,0.044524,-0.048101,-0.002524,0.014255,0.02864,0.014215,0.00233,-0.122774,-0.029312,-0.031198,-0.011599,0.024233,0.009239,-0.033405,0.059192,-0.014381,0.085249,0.016928,0.050144,-0.060547,0.007836,0.035249,0.009737,-0.006356,-0.065529,0.023366,-0.014864,0.020754,-0.014454,0.036961,-0.075069,-0.162608,0.037611,-0.116265,-0.123639,0.010216,-0.091044,0.041593,-0.030168,0.029541,0.077881,0.150231,0.056017,-0.061595,0.028221,-0.006699,0.043798,-0.039418,0.01318,-0.066687,-0.02877,0.060191,-0.026647,0.044521,0.080609,-0.066239,-0.011344,-0.049835,0.031217,0.019858,0.030414,-0.014845,0.046936,0.041754,-0.0,0.004298,-0.059453,-0.046803,-0.096327,0.052339,-0.038345,-0.000382,0.096152,0.041993,0.053743,0.028475,0.008427,-0.008975,0.045032,0.0175,0.018434,0.00063,0.058697,-0.030176,0.007244,-0.028543,0.071286,0.091344,-0.036082,-0.034703,0.017423,0.078989,0.025245,-0.021471,0.02839,0.012701,-0.022097,-0.107517,0.112726,-0.058799,-0.061472,0.06553,-0.074839,-0.064582,-0.024472,-0.058375,0.123153,-0.028664,0.024591,-0.013037,-0.075315,0.011288,0.010577,0.039115,-0.034327,0.063462,0.009717,0.096441,-0.028284,0.004055,0.074854,0.046216,-0.035941,0.032148,-0.065099,0.069067,0.092644,0.002401,0.022725,0.035344,0.002863,0.044687,0.008084,0.090207,-0.020522,0.052992,-0.114016,-0.024321,0.069412,0.095178,-0.054028,0.002039,0.0324,0.023551,0.029541,0.069514,-0.021185,0.015931,0.068754,-0.013437,-0.083504,0.034402,-0.054525,0.008289,0.025747,-0.006079,-0.018582,-0.029782,0.109626,-0.064262,-0.0,-0.086569,-0.081397,-0.003134,-0.038944,0.055824,-0.018928,-0.076746,0.005109,-0.039546,-0.081262,-0.041456,-0.004777,-0.06191,0.002967,-0.010697,-0.114741,0.040464,-0.05058,0.009511,-0.064604,-0.051448,0.016116,0.01394,-0.030015,-0.072818,-0.037358,-0.005284,0.055713,0.027591,0.020028,-0.09134,0.061068,0.075796,-0.126609,-0.101102,0.047781,0.044888,-0.05937,0.017049,0.002743,-0.057572,-0.0541,0.06105,-0.012333,0.041357,-0.033658,-0.013848,-0.016545,0.047244,-0.14799,-0.033371,-0.068825,0.065739,0.059125,-0.038609,-0.050043,-0.051341,-0.021531,0.019667,-0.041132,0.044898,-0.039084,-0.008946,0.012795],"category":"Impersonation Fraud","source":"seed_minilm"},{"embedding":[-0.047606,-0.025695,0.041059,-0.007878,0.015533,-0.025851,-0.015749,-0.023922,0.009798,-0.088613,0.041308,0.015848,-0.012048,-0.050651,-0.000878,0.017644,0.031398,-0.077004,-0.088901,-0.010855,0.098266,0.034774,-0.026866,0.019651,0.004949,-0.04607,-0.030657,0.056137,0.039634,0.031627,-0.041645,0.099062,0.006381,0.01658,0.003426,-0.045667,-0.026521,0.059464,0.060573,-0.00682,0.007803,-0.063911,-0.02373,0.009034,0.052709,0.052986,-0.065555,0.010051,0.014629,0.04012,-0.007155,0.06991,-0.047239,0.011319,-0.067555,0.043781,0.054386,0.058946,0.035822,0.068357,0.004997,0.080679,0.009365,-0.001032,0.036409,0.049861,-0.063004,-0.072833,0.079315,0.023155,0.020674,0.007407,-0.020132,0.023159,-0.044566,0.078419,4.2e-05,-0.02732,0.031783,0.016686,0.037151,-0.020412,0.029995,-0.012743,-0.010557,-0.046551,0.011559,0.117323,-0.062843,-0.016659,0.035163,0.111649,0.011953,-0.017716,-0.069634,0.032731,-0.044558,0.01848,-0.118312,0.019068,0.034086,0.062643,-0.088747,-0.011667,-0.031042,-0.035635,0.053916,-0.03715,-0.011071,0.012469,0.090704,-0.00832,0.008451,0.000142,-0.031879,0.078744,-0.019755,0.116045,0.09022,-0.023126,-0.013072,-0.02977,-0.040975,-0.110142,0.017255,0.016578,0.094425,-0.0,-0.043901,0.018113,-0.038491,0.074753,0.098824,-0.106543,-0.032674,0.015892,0.023799,0.06817,-0.074428,-0.032759,-0.009839,-0.091749,-0.02359,-0.033139,0.163027,0.048153,0.008317,-0.013379,0.068655,-0.09198,-0.006282,0.029283,0.114563,0.109497,0.009918,-0.047949,0.082278,-0.000823,-0.048671,0.046252,-0.016153,0.031702,0.073225,-0.041482,0.019618,-0.02402,-0.043726,-0.083753,0.007325,0.014598,-0.015443,0.005577,0.005746,-0.109281,0.026007,0.00881,0.040694,0.006385,-0.041885,0.01064,-0.031884,-0.03355,-0.002082,-0.023808,-0.003321,0.027885,-0.030943,-0.06774,0.087338,0.013949,-0.06803,-0.012999,0.004456,-0.063575,-0.060848,-0.049764,0.015618,-0.044779,-0.006818,0.018452,0.03227,-0.032666,-0.044748,0.045834,-0.004915,-0.012285,-0.038179,0.069685,0.047071,0.019063,-0.04331,-0.026154,0.109002,-0.015677,0.011788,-0.044045,-0.048295,0.059186,-0.11357,0.032897,0.006747,0.034389,-0.01553,-0.0,-0.065001,-0.06966,-0.062882,-0.039517,0.012532,-0.062399,0.019472,0.110343,-0.075516,-0.028388,0.070677,0.031351,0.009626,-0.055724,0.043719,0.025065,0.0938,0.055213,-0.098649,0.115762,0.040523,-0.04416,0.023974,0.030345,0.002425,-0.035359,0.072882,0.013709,0.009824,0.024347,-0.01445,-0.084578,-0.069839,0.1156,-0.057903,-0.024598,0.036173,0.011952,-0.03096,0.054685,0.038106,0.03133,-0.028385,-0.017306,-0.082814,-0.012476,0.069544,-0.043741,-0.121324,0.033775,0.097224,0.008704,0.04312,0.02671,-0.01572,0.024243,0.040474,-0.096436,-0.028381,-0.035368,0.042412,0.076957,-0.023436,0.0379,0.073213,-0.019048,-0.014759,0.031434,0.070643,-0.011352,0.015078,-0.037516,-0.038139,0.043421,-0.024795,-0.092167,-0.07433,0.018359,-0.030556,-0.018763,0.104013,0.022948,-0.076402,-0.032735,-0.043937,0.002932,0.067663,0.091667,0.095101,-0.000698,-0.010478,0.023269,-0.034927,0.028263,-0.126435,-0.0,0.018093,-0.018825,0.099196,-0.040108,0.04082,-0.043649,-0.068523,-0.032969,-0.025382,-0.010874,0.014731,-0.021663,-0.031516,-0.001992,-0.006102,-0.037961,0.099808,-0.122807,0.036699,-0.000439,-0.052583,-0.02929,-0.033897,0.051691,-0.04859,0.04228,-0.051993,0.019691,0.000772,0.01741,0.03628,0.01829,-0.037548,-0.004924,-0.100989,0.007788,0.007635,-0.090756,-0.01407,-0.031576,0.050415,-0.002547,-0.027345,0.061284,0.029113,-0.025277,0.017198,-0.066893,0.014226,-0.021809,-0.020118,-0.068023,-0.04214,-0.000485,0.044269,-0.073151,0.066983,0.001615,-0.051854,0.001608,0.00226,0.026725,-0.08411,-0.116116],"category":"Impersonation Fraud","source":"seed_minilm"},{"embedding":[0.046465,-0.01951,0.01149,-0.001798,-0.022079,-0.041096,0.041892,0.002529,-0.063806,-0.009161,-0.014414,-0.102962,-0.016867,-0.048448,-0.004496,-0.031383,-0.022441,-0.016115,0.029235,0.034284,0.076128,0.026189,-0.084901,-0.031122,0.133323,-0.008502,-0.027915,-0.008003,-0.040868,-0.011984,0.044998,0.017128,-0.077021,-0.131819,0.003739,-0.015697,0.006679,-0.011505,0.085062,-0.03072,-0.070975,0.030938,-0.040016,0.032483,0.060395,-0.013633,-0.004232,0.026635,0.031974,0.107967,-0.038071,-0.001972,-0.015051,0.090554,-0.017996,-0.037441,0.015003,0.066242,0.037653,-0.098289,0.004735,-0.001008,0.057671,-0.008301,-0.058366,0.017848,0.016559,-0.04538,-0.023714,-0.087617,-0.019229,-0.062431,-0.036119,-0.047138,-0.010972,0.046154,0.018933,0.113857,-0.023288,-0.001756,-0.030938,-0.025778,-0.017106,-0.000525,0.056347,-0.009515,0.065042,0.035025,-0.036621,0.051553,0.110044,-0.0089,0.060251,0.004698,-0.024483,-0.050017,-0.038698,-0.048101,0.047147,9.3e-05,0.053114,0.018413,-0.064474,0.05182,-0.006624,0.00296,0.004369,0.074912,-0.003122,-0.065585,0.001883,0.004462,-0.016298,0.006403,-0.052668,0.011292,-0.095764,0.001174,-0.009913,-0.010626,0.055517,0.115035,-0.031573,0.019878,-0.0015,-0.1076,0.015165,0.0,0.016369,0.124902,0.025367,-0.088855,0.04861,-0.01391,0.064567,-0.024189,0.008093,0.041096,-0.042779,-0.011899,0.02107,-0.091409,-0.12256,0.075491,0.02451,0.036636,0.004636,0.161521,0.027581,0.035248,-0.013995,-0.011923,0.022684,0.104224,-0.051668,0.019971,0.02645,0.004905,0.077519,-0.053186,0.093421,-0.015487,-0.027471,0.018145,0.028099,-0.043843,-0.054083,0.004218,0.080935,-0.000733,0.041173,0.023045,-0.023758,-0.041579,0.029708,0.148872,0.03679,0.062931,-0.07258,0.013572,-0.103111,-0.031343,-0.05683,-0.045082,-0.023683,0.01968,0.02225,-0.067603,0.070511,-0.06109,-0.022128,-0.014002,-0.030849,0.010724,0.029849,-0.056763,-0.038289,0.019025,-0.078253,0.011802,0.061673,0.080941,-0.015821,-0.052,-0.056643,-0.014103,0.045104,0.01655,-0.071226,-0.028531,-0.104585,-0.027305,0.031639,0.076255,0.03273,0.062193,-0.036308,-0.027288,0.089189,-0.006353,0.078964,0.008742,0.022037,-0.0,-0.016828,-0.062354,-0.081153,-0.016521,-0.067875,0.009631,0.101461,0.035399,-0.0144,0.017699,0.016124,-0.021634,-0.000116,0.02131,-0.03641,0.0215,-0.00513,-0.011084,-0.008408,-0.043037,-0.012447,0.046512,0.107067,0.127764,0.008113,0.062971,-0.021558,0.00124,0.019931,-0.031925,0.006286,-0.12097,-0.097234,-0.019692,-0.012165,-0.093174,-0.019067,-0.056298,0.049723,0.058247,0.000595,0.08377,-0.011844,-0.017734,0.024156,0.00396,0.043524,-0.020869,-0.007646,-0.089254,0.055319,-0.011512,0.059864,0.00639,0.052018,0.085788,0.087692,0.003898,0.051238,-0.061324,0.007072,0.021789,-0.007215,0.113602,0.020138,0.023632,0.028158,-0.067188,0.140478,-0.07138,-0.032767,-0.021901,0.031541,-0.009359,0.052123,0.053342,-0.03168,-0.000428,0.085874,-0.027685,0.068522,0.025805,0.010803,0.034152,-0.038336,-0.088431,-0.002983,0.001847,0.081825,0.006515,-0.038027,-0.025825,0.026724,0.047203,0.035125,-0.0,-0.004817,0.042346,-0.031996,0.074809,0.073914,-0.01794,0.016637,-0.003642,-0.081309,-0.070765,-0.004346,-0.009225,-0.027257,-0.041485,-0.005188,-0.052411,0.022607,-0.002522,0.048253,-0.022458,-0.009896,-0.037549,-0.002653,-0.036215,0.006512,-0.017687,0.033275,0.079412,0.032856,-0.11354,-0.110912,-0.018886,0.000816,-0.038143,-0.100223,0.004217,0.070493,0.036676,0.042683,0.038662,-0.035796,-0.052119,0.014385,-0.056869,-0.025406,-0.003283,-0.044094,-0.058713,-0.025387,-0.111244,0.041892,-0.013316,0.041443,-0.040463,-0.019831,0.012186,-0.126076,0.018988,-0.072105,-0.017978,0.067353,0.019459,-0.058357,-0.088276],"category":"Impersonation Fraud","source":"seed_minilm"},{"embedding":[-0.0159,-0.03963,0.014247,-0.038703,0.027223,-0.016009,-0.016832,0.017723,0.11767,0.034221,-0.01014,0.051816,-0.027504,0.076481,0.003484,0.022036,-0.042132,-0.098115,-0.092264,0.084079,-0.012459,0.009833,-0.084505,0.006619,0.034169,-0.099011,0.003096,-0.015065,-0.006148,0.025166,-0.095173,0.00805,-0.016494,0.025066,0.103799,0.027115,0.049982,0.079863,0.025699,-0.026973,0.028503,0.025694,0.073301,0.022889,0.049502,0.071993,0.004264,-0.028721,0.059342,0.105524,-0.06612,0.054465,0.015373,-0.027578,-0.039667,0.020816,0.053437,0.046843,0.052575,0.030946,0.03299,-0.027982,0.000602,-0.052382,0.069821,0.043773,-0.05126,-0.047165,-0.056193,-0.031172,0.032784,0.030533,-0.116925,0.056074,-0.008053,0.053309,0.030693,-0.089005,0.063043,0.069266,-0.022605,-0.026313,-0.023366,0.032406,0.011021,0.036852,0.01867,-0.034593,0.063708,0.053885,-0.061583,-0.005217,0.063869,0.03294,-0.033025,-0.050548,0.082219,-0.032319,-0.040785,0.03228,0.014874,-0.010947,0.047085,0.034496,0.023043,-0.108264,0.067571,0.016991,0.055608,-0.120572,-0.056639,-0.024055,-0.041921,-0.046559,-0.024621,-0.009599,-0.062632,-0.035817,-0.022644,-0.064791,-0.010548,-0.037877,-0.065193,-0.107504,0.052312,-0.042081,0.107758,0.0,-0.038446,0.0079,-0.003515,0.046484,0.070935,-0.03047,0.059282,-0.062357,-0.031562,-0.015702,0.001186,0.029173,0.048645,0.00743,-0.083845,-0.018264,0.157796,0.047944,-0.047769,0.024493,0.023981,-0.038724,0.076628,-0.027537,-0.034904,0.064687,-0.008209,0.044266,0.05766,-0.000198,0.024258,0.036835,-0.009646,0.005937,-0.058147,-0.023847,0.091068,-0.027845,0.075451,-0.011315,-0.011728,-0.0305,0.007355,0.000591,0.064934,-0.031737,0.009667,0.047792,0.01309,0.076476,-0.093213,0.059912,0.007242,0.002452,-0.055446,-0.009482,0.035126,0.054434,-0.062304,-0.054399,0.034504,-0.018292,0.023449,-0.087252,-0.001575,-0.127491,0.032217,0.011823,0.028569,-0.026977,-0.021536,0.008058,0.115224,0.039152,-0.10182,-0.050367,-0.039973,-0.008191,-0.083824,0.059194,-0.078207,0.013168,0.003976,-0.056109,-0.041216,0.024028,-0.087478,0.047895,-0.009755,0.029292,-0.025169,-0.029997,-0.062092,0.057552,-0.041046,-0.0,-0.084127,-0.003762,-0.052259,-0.031501,0.015997,-0.026889,-0.034459,0.002853,-0.020276,0.045977,0.026833,0.046005,0.006177,-0.027041,-0.003928,0.04693,-0.021443,0.024268,0.011733,0.029875,-0.016577,-0.015514,-0.047727,0.066189,0.02805,0.027431,-0.034766,0.027798,0.065901,-0.023193,0.089012,0.040703,-0.014523,0.083158,0.025845,0.040511,0.095046,-0.132633,-0.009514,-0.066729,0.022441,0.00492,0.04393,0.028436,-0.011208,-0.00867,-0.001932,-0.043278,-0.031632,0.103413,0.116211,-0.009193,0.045263,-0.01469,-0.046435,-0.006806,0.014724,0.008515,0.038311,-0.041958,-0.036763,0.012639,-0.077563,-0.017975,-0.041305,0.119587,0.084455,0.051381,0.012576,0.008482,-0.036873,0.084643,-0.026014,-0.052638,-0.053794,-0.023515,-0.089441,0.001744,-0.059891,-0.013815,0.094179,-0.024477,-0.052597,-0.009009,0.013523,0.005968,0.061871,0.081642,-0.11586,-0.079134,-0.068633,-0.089401,-0.000497,0.102776,-0.011687,-0.0,0.009593,-0.074093,0.008229,-0.034626,0.03815,-0.017891,-0.014,0.014752,-0.07387,-0.046408,-0.072011,-0.05751,0.002496,-0.009831,0.058115,-0.117612,-0.132472,-0.010951,0.023908,-0.043045,0.066361,-0.032823,0.014548,-0.053457,0.03819,0.023079,0.009289,0.082198,-0.015501,0.019659,-0.023339,-0.01761,-0.026273,-0.008641,-0.067616,0.003832,-0.005061,0.008053,0.023662,-0.064474,0.033477,0.021987,-0.057019,-0.004864,-0.066098,0.024725,-0.064078,-0.028888,0.019712,-0.062756,-0.07154,-0.016511,-0.013999,0.064977,-0.048146,0.007961,-0.005181,-0.046924,0.050069,0.095521,0.002583,0.025892,-0.096038,-0.108967],"category":"Impersonation Fraud","source":"seed_minilm"},{"embedding":[-0.047427,0.012261,0.028668,0.010834,-0.010268,-0.038613,0.071539,-0.119944,0.155151,0.020241,0.048843,0.022418,0.040783,-0.067418,-0.101179,-0.021687,-0.039467,-0.136053,-0.094709,0.024765,-0.021439,0.071405,-0.070886,0.059048,0.008187,-0.005026,-0.112908,0.074545,0.001866,-0.040904,0.029035,0.041831,0.027056,0.04051,-0.029614,-0.046737,-0.044988,-0.082586,0.020529,0.013186,0.018509,-0.005908,-0.009725,-0.05534,-0.01918,0.066032,-0.012036,0.060994,0.073855,0.05848,0.02225,-0.019378,-0.104877,-0.016829,-0.050993,0.041435,0.042579,0.026437,0.041418,-0.002997,0.046155,-0.066178,-0.010531,0.041365,-0.049496,0.0206,-0.060657,-0.053247,-0.014705,-0.084244,0.043302,-0.089147,0.02896,0.11232,0.047212,0.017836,0.038503,-0.095022,0.004543,0.072027,-0.049869,-0.06843,-0.030562,0.005611,-0.009796,-0.001342,0.058513,-0.014793,0.061864,0.010262,0.03862,-0.010477,0.093845,0.01101,-0.037022,-0.054228,0.001282,-0.008533,-0.092652,0.032647,0.036722,0.011089,0.011869,0.013818,0.036106,-0.104936,-0.023464,0.038212,0.027162,-0.057256,-0.049404,-0.043279,-0.023389,0.001494,-0.057096,0.111877,-0.022358,0.06271,0.054827,-0.121792,0.023256,0.053424,-0.016072,-0.094066,-0.070025,-0.063711,0.119096,-0.0,-0.054548,0.037493,0.024835,-0.112098,0.089387,-0.002403,-0.028613,0.063725,-0.065224,0.02037,0.014934,-0.045655,0.040234,0.014647,-0.074785,-0.019102,0.036283,0.079098,0.004918,0.05166,0.038662,0.021303,0.014219,0.022141,-0.029153,0.023816,-0.033035,0.014595,0.082409,0.028011,-0.002531,0.011925,-0.038178,-0.025636,-0.008981,-0.025,0.05624,-0.04576,0.000591,-0.017562,-0.028526,-0.021391,-0.063158,0.001987,-0.04039,0.056306,0.002683,0.022951,0.047792,0.083632,-0.070144,-0.026714,0.060948,0.027504,0.012907,-0.072249,0.012953,-0.003764,-0.043747,-0.060342,0.065176,-0.008066,-0.019328,0.024628,-0.080235,-0.164721,0.025407,0.002109,-0.005367,0.010584,0.013242,0.06416,0.071895,0.025175,-0.038296,-0.029524,-0.0203,0.034867,0.026459,0.042381,-0.041005,0.004845,0.01573,0.022885,-0.048738,0.07819,-0.027361,0.046448,0.001762,0.005574,-0.037772,0.024957,0.018422,0.068646,0.013087,-0.0,-0.062387,-0.044023,-0.074145,0.026315,0.029692,-0.028881,-0.033249,0.05073,0.00755,0.01625,0.02529,0.047199,0.030575,-0.057823,0.0884,-0.038066,0.061616,-0.024423,-0.080477,-0.009831,-0.041868,-0.01753,-0.00152,-0.033113,-0.05194,0.00765,0.068932,0.051374,0.055928,-0.025642,0.056797,0.054815,-0.03021,0.093065,-0.019411,-0.03031,0.030881,0.049985,-0.003233,-0.021502,0.039111,0.023316,0.034161,0.014027,-0.033295,-0.04189,0.066559,-0.021883,-0.031076,0.038682,-0.071005,0.047305,0.081838,0.010788,-0.083435,0.031909,0.014969,0.030613,0.117525,-0.048038,0.016596,0.050459,0.018423,-0.027029,0.008202,0.047383,0.012067,0.095435,0.08138,0.006233,0.004958,-0.012043,0.027109,-0.027288,0.026482,-0.025471,-0.048015,-0.051122,-0.042624,-0.0491,0.126979,0.018953,0.027512,0.068084,-0.025223,-0.02533,0.02481,0.031889,-0.013318,0.043831,0.021452,-0.092498,-0.074611,0.054233,-0.037697,-0.0,0.023251,-0.100529,0.11628,-0.012104,0.103124,-0.034035,-0.043301,0.049964,-0.039208,-0.033911,-0.006835,-0.046319,-0.000524,-0.057515,0.007095,-0.045984,-0.013491,-0.02049,-0.003751,-0.031271,-0.078339,-0.023926,0.058677,-0.137101,-0.031752,0.013966,0.01281,0.096147,0.052197,-0.090543,-0.008072,0.028137,-0.010988,-0.028562,-0.089552,0.003438,-0.018577,-0.047911,-0.040898,-0.09726,0.018173,0.015128,-0.019341,0.028903,-0.015229,0.025477,0.006156,-0.080254,0.06341,-0.026091,-0.088488,-0.013879,0.060211,0.140497,-0.053786,-0.017031,-0.012307,-0.054357,-0.024739,0.088305,0.063042,-0.013289,0.016963,-0.000332],"category":"Impersonation Fraud","source":"seed_minilm"},{"embedding":[-0.008519,0.00508,-0.090819,-0.036338,5.5e-05,-0.049102,0.057651,0.029155,0.029607,-0.024666,0.05965,0.075307,0.023991,0.022814,-0.03093,0.040623,0.035726,-0.088116,0.029027,0.030717,-0.011358,0.122594,-0.005765,0.009393,0.008654,0.103761,-0.031216,0.028884,0.040728,0.008131,0.03491,0.078585,-0.036874,0.062858,-0.00667,0.016617,-0.097192,0.004055,0.095666,-0.080103,0.051229,-0.071207,0.002479,0.066089,0.014302,-0.043366,-0.038623,0.058609,0.034422,0.105473,0.097064,-0.046732,-0.012822,0.150077,-0.034218,-0.05284,0.024113,0.030408,-0.051933,0.024185,-0.094509,0.143553,0.043145,-0.012933,-0.026927,0.023428,-0.01783,-0.088732,0.03984,-0.039254,0.023691,-0.043533,0.019741,0.047403,-0.025538,-0.001624,-0.03431,0.01789,-0.026412,-0.021425,-0.007851,-0.012891,0.005817,0.024585,-0.027239,0.027054,-0.002308,0.026541,0.010737,-0.016628,0.072103,0.038975,0.004894,-0.001152,-0.080411,-0.09543,-0.027231,0.037882,-0.047037,0.016728,-0.010316,0.078388,-0.098089,-0.018276,-0.034153,-0.073391,0.048046,-0.024948,0.027031,0.05148,-0.017146,0.051137,0.032989,0.020816,-0.062691,0.076761,-0.08542,0.096515,-0.028339,-0.093956,-0.075412,0.03082,0.009502,-0.006769,0.001956,-0.031778,0.036048,0.0,-0.097503,-0.017886,0.045644,-0.004577,-0.010514,-0.104518,0.015085,-0.023589,0.000399,0.010699,-0.064099,-0.011971,-0.004059,-0.007851,-0.028947,-0.060642,0.06241,-0.039208,0.073677,0.051269,-0.006557,-0.035103,-0.007773,0.085839,-0.033696,0.094408,-0.007523,0.011596,0.026065,0.011788,-0.027096,0.05542,-0.073297,-0.005504,-0.028892,0.012873,0.033868,0.019457,-0.097294,-0.007858,0.027545,-0.006469,0.012825,0.024587,-0.016415,0.013058,-0.057957,0.084751,0.009339,0.035424,-0.077235,0.015175,0.004309,-0.01077,-0.060753,-0.035032,-0.053628,-0.031912,0.033231,0.01296,0.062964,-0.041565,-0.089699,0.026121,-0.025688,-0.075866,-0.000787,-0.089065,0.015267,0.00246,0.059148,0.069877,0.066337,0.064479,-0.034144,0.034756,-0.02856,0.049068,-0.011266,0.006489,-0.048909,-0.055197,0.055577,0.046557,0.058559,0.035762,-0.014811,-0.072774,-0.098002,-0.003502,-0.091038,0.048355,-0.044735,0.011316,0.00178,-0.0,0.063644,-0.064584,-0.071476,-0.025381,0.017003,-0.024483,-0.014015,0.104949,-0.031549,0.007887,0.001321,0.052569,-0.007122,-0.003994,0.037205,-0.004229,-0.016841,0.07036,-0.037074,0.030249,-0.019879,0.058701,0.056955,-0.011842,-0.068632,-0.012776,0.070058,0.041939,-0.030894,-0.007798,0.017013,0.010825,-0.039399,0.086832,-0.084673,0.013943,0.080232,-0.050373,-0.038596,-0.044814,-0.078779,0.099776,-0.095129,0.07213,-0.031223,-0.08817,0.007839,0.066193,0.048595,-0.042928,0.075255,0.058257,0.077361,-0.007814,0.04043,0.104831,0.005545,-0.083897,0.074765,-0.069659,0.007738,0.083363,-0.076711,-0.027794,0.048965,-0.061896,0.083362,0.021515,0.087651,-0.016529,0.031442,-0.069547,0.000661,0.074887,0.140132,-0.076782,0.005296,0.050132,-0.003826,-0.029285,0.095747,-0.056468,-0.016239,0.037036,-0.0327,0.007124,0.058472,-0.065426,-0.030838,-0.002351,0.016599,-0.025687,-0.1,0.075575,-0.05934,-0.0,-0.034582,-0.012523,0.048053,0.021081,0.072503,0.037117,-0.022167,0.057633,-0.066608,-0.06089,-0.013064,0.00038,-0.079027,0.012326,-0.061883,-0.020001,0.049835,0.005487,-0.039856,-0.048779,-0.140931,-0.003406,0.044839,-0.054722,-0.005961,0.002307,-0.032451,0.008006,0.015196,0.030273,-0.052291,0.01991,0.062577,-0.101856,-0.061156,0.010135,-0.003196,-0.060817,0.049368,-0.010628,-0.112793,-0.035884,0.046043,0.016715,0.011844,-0.017164,-0.058411,-0.016728,0.007179,-0.091664,0.002517,-0.046451,0.053821,0.003089,-0.050401,-0.028968,-0.041512,-0.04809,-0.001953,-0.024445,0.058121,0.029963,-0.022427,0.0026],"category":"Impersonation Fraud","source":"seed_minilm"},{"embedding":[0.012352,-0.108026,-0.018283,-0.063126,0.125442,0.001201,0.030595,-0.065414,0.026451,0.030003,0.079568,-0.013546,-0.058753,-0.041858,-0.011787,-0.067195,-0.138875,-0.074794,-0.075461,0.024737,-0.034151,-0.068431,-0.02221,0.030115,-0.027771,-6.1e-05,-0.040459,0.06518,-0.02665,-0.068155,0.022312,-0.018719,0.003599,0.016795,0.045548,0.026111,-0.029593,0.00422,-0.072817,-0.050681,-0.046911,-0.061798,-0.073532,-0.000306,0.091839,0.049682,0.056247,0.019618,0.044945,0.036655,0.055936,0.054348,-0.038112,-0.022002,-0.068093,0.067769,0.064394,0.020735,-0.048486,0.06914,-0.030151,-0.002559,-0.039562,0.050772,-0.030689,0.074151,-0.014177,-0.081705,0.001804,-0.056011,-0.078953,-0.039404,-0.065212,0.071512,0.043951,0.106246,0.000626,-0.04211,0.068794,0.059965,0.01503,-0.033375,0.030733,-0.02812,0.003157,-0.005163,0.071843,-0.03323,-0.022971,0.015611,0.129566,0.03608,0.113726,0.089727,-0.045968,0.004367,0.00274,-0.023115,-0.068472,0.0189,-0.007388,0.011954,-0.019334,0.047431,-0.028471,-0.043434,0.040004,0.056762,-0.069419,-0.022704,-0.00763,-0.021033,0.017974,0.037563,-0.024279,0.077352,-0.161132,0.000107,0.043569,-0.045598,0.010354,0.082331,-0.030124,-0.057225,-0.097104,0.016616,0.111217,0.0,-0.061552,0.014232,0.00567,-0.020652,0.029195,0.009209,0.036647,0.0123,0.004031,-0.023942,0.006882,-0.001836,0.017855,-0.033715,-0.046199,-0.074557,0.06753,0.057607,0.019593,0.04085,0.042711,-0.08612,-0.028017,-0.047347,0.024751,0.058359,-0.01747,0.022606,-0.009098,0.02097,-0.062846,-0.02614,0.018512,-0.032041,-0.005895,0.016962,0.065685,-0.035188,0.006609,-0.037851,0.033782,-0.028015,0.011527,-0.029948,-0.072577,-0.113019,0.080754,0.082512,0.047839,0.074986,-0.01474,-0.017296,-0.049345,-0.014858,-0.01762,0.076665,0.016428,-0.056952,-0.030772,-0.086591,0.074241,0.04206,0.001766,-0.062452,-0.031574,0.005771,0.013949,-0.133339,-0.044811,0.032873,-0.00556,-0.016679,0.130928,-0.033357,-0.007911,-0.00763,-0.08486,0.081964,-0.047715,0.130121,-0.00119,0.018824,-0.003447,0.055924,0.045197,0.029233,-0.000551,0.065524,-0.014667,0.005782,0.037794,0.008576,0.084672,0.055613,0.033391,-0.0,-0.005882,-0.039981,-0.016576,-0.044282,0.041504,0.03038,0.032361,0.137728,-0.036068,0.01566,0.033788,-0.009103,-0.036516,-0.106173,0.079505,-0.034012,0.013983,0.052267,-0.045855,0.059678,-0.000843,-0.017033,0.008559,0.074839,0.02437,0.007545,0.074636,0.067406,-0.012397,-0.037726,0.057756,-0.080006,-0.12631,0.110511,0.014891,-0.124387,0.011717,-0.021612,-0.036791,-0.072418,0.017613,0.011181,-0.022666,-0.031264,0.006515,-0.024411,0.07359,-0.008809,0.086817,0.047883,-0.01007,0.037181,0.083785,-0.008329,-0.015569,0.015695,0.094335,-0.027976,-0.046945,-0.059048,0.005101,0.043588,-0.034749,0.049333,0.078097,-0.045009,-0.01989,-0.034438,0.064278,-0.027647,0.034865,-0.035449,0.014088,-0.000996,0.047103,0.024871,-0.051603,-0.008359,0.00676,0.04565,0.060338,0.029891,-0.105857,0.076998,-0.024866,-0.064226,0.02027,-0.050583,0.002166,-0.00814,0.023298,-0.033276,-0.034951,0.051238,0.055319,-0.0,0.000421,-0.000356,0.103676,-0.015366,0.017546,-0.047549,0.018299,-0.057919,0.017514,-0.098629,-0.002046,0.002317,0.034689,-0.013941,0.002117,-0.062403,0.047802,-0.017318,-0.01005,-0.020151,-0.112253,-0.045343,0.024163,-0.055421,-0.004401,0.005706,0.093898,0.083971,-0.035033,0.027665,-0.095192,-0.056873,-0.014757,0.035109,-0.065391,0.025136,0.010219,-0.030281,-0.090189,0.016519,0.056236,-0.000115,0.063262,-0.002338,-0.010177,0.017833,-0.016603,-0.013816,0.083284,-0.064755,-0.005887,-0.002677,-0.01788,0.014317,-0.046145,-0.02189,-0.012477,-0.016509,-0.016436,0.069687,0.065303,-0.055433,-0.058334,-0.022149],"category":"Impersonation Fraud","source":"seed_minilm"},{"embedding":[-0.075838,0.049083,0.034309,0.004952,-0.012454,0.029491,-0.014773,-0.007245,0.002953,0.02017,0.087062,-0.000168,0.040505,-0.102314,-0.037574,0.011855,0.105617,-0.062621,-0.019338,0.04452,0.012168,0.082193,-0.002981,-0.01317,-0.008498,0.062373,-0.039125,-0.055473,0.101341,0.026366,0.018827,0.069938,0.033304,0.04728,0.03285,-0.006446,0.047729,-0.087674,0.006035,-0.018437,0.069405,-0.067925,-0.038797,-0.001093,0.025771,0.056888,-0.024765,0.018928,0.010517,0.005652,-0.051776,-0.116179,-0.083331,0.047504,-0.088387,0.024878,0.079113,-0.030253,0.005064,-0.049785,0.049982,0.023753,0.023633,0.042868,-0.101868,0.033169,-0.038349,-0.002339,0.056453,0.017502,0.072008,0.056105,0.02143,-0.015541,-0.052903,0.054686,0.003266,-0.010598,0.074133,-0.095008,0.012445,-0.089382,-0.059555,0.037267,-0.005043,-0.03446,-0.051109,0.054874,0.029248,-0.051882,0.052881,0.029032,-0.017102,-0.105528,-0.075999,-0.045746,-0.017393,-0.00481,-0.065096,0.051857,0.054648,0.079201,-0.036722,0.058462,0.044635,0.009479,0.007076,0.014308,-0.024464,0.007052,0.082572,-0.021929,0.037005,-0.02241,-0.036955,0.074484,0.000271,0.071972,0.02849,-0.077746,0.038394,-0.011267,-0.109442,-0.02078,-0.029584,-0.001247,-0.031381,-0.0,0.054681,-0.018436,0.043092,-0.099139,0.04997,-0.059535,-0.004521,-0.032015,-0.021151,0.043822,0.004287,-0.06015,0.086403,-0.067974,-0.125201,-0.061761,-0.035886,0.042636,0.001121,0.114813,0.037346,-0.088745,-0.007039,0.105505,-0.102758,0.001974,0.012661,-0.027026,0.046009,-0.031519,0.048172,0.08062,0.111278,0.058906,0.075785,0.011612,0.025569,-0.03765,-0.002999,-0.015534,0.015889,-0.023589,0.054448,-0.065584,-0.024493,-0.084606,-0.048009,-0.056829,0.101002,-0.044606,-0.03888,0.033105,-0.063413,0.002466,-0.089802,0.026636,-0.027466,0.127344,-0.002537,-0.024783,0.007613,-0.016232,-0.050196,0.009779,-0.040307,-0.041626,-0.099829,0.001746,-0.025014,-0.005611,0.067099,0.089449,0.05759,0.067964,-0.033205,0.002818,0.047656,-0.014097,0.015644,0.035441,-0.035588,-0.083414,0.049999,0.023299,0.041143,0.017286,-0.015509,0.006797,0.004695,-0.022553,0.012493,0.01894,-0.118179,-0.00215,-0.000997,-0.0,-0.007803,-0.04167,-0.091781,0.038836,0.020017,-0.038186,-0.046317,0.034421,-0.01795,-0.066473,0.01654,0.024724,-0.025566,0.021886,0.090731,-0.001631,0.047476,-0.024282,-0.018605,0.110154,0.054669,0.000263,0.023198,0.079795,-0.087353,0.016024,0.010476,0.014531,0.010582,0.111398,-0.024133,-0.07076,-0.074394,0.056011,-0.001543,-0.054428,0.092553,0.00914,-0.029183,-0.019988,0.014523,0.052835,0.025648,0.05123,-0.053301,0.023696,0.035478,-0.011083,-0.039209,-0.039983,-0.025989,-0.005737,0.060262,0.067794,-0.023869,0.031232,-0.019433,-0.007289,-0.013522,-0.005864,0.050081,0.062186,-0.078738,-0.121013,0.068685,0.039132,-0.043373,-0.027252,0.064743,-0.040897,-0.01836,-0.027849,-0.121884,-0.101152,0.031579,0.019902,0.020247,0.047016,-0.061612,0.016542,0.085179,0.025559,-0.04255,-0.000229,-0.054957,0.027613,0.018587,-0.007846,-0.009636,0.053726,-0.042777,0.035612,-0.025235,0.036373,-0.030007,-0.0,-0.02807,0.008766,0.002614,-0.006358,0.093316,-0.016929,-0.010074,-0.097588,-0.030976,-0.049414,0.01712,-0.102783,-0.038284,-0.048217,-0.004018,-0.036052,-0.01483,-0.045504,-0.078817,-0.011963,-0.131801,0.03478,-0.029771,-0.064073,-0.042299,-0.014472,0.005015,-0.035414,0.073016,-0.022465,-0.097812,0.111841,-0.016087,-0.057312,0.0234,0.002481,0.019792,0.003501,0.024427,-0.081263,0.007094,0.081817,-0.023097,0.048644,0.072716,0.003255,-0.067861,-0.019402,0.030155,-0.024731,-0.005816,-0.052198,0.051383,0.020351,-0.020429,0.014879,0.073129,-0.002605,-0.019586,0.067647,0.070228,-0.071007,0.070853,-0.008549],"category":"Impersonation Fraud","source":"seed_minilm"}] \ No newline at end of file diff --git a/build_err.txt b/build_err.txt new file mode 100644 index 0000000000000000000000000000000000000000..aba1ab843bb2598234e9ef1c23ca4f27b8abd951 --- /dev/null +++ b/build_err.txt @@ -0,0 +1,296 @@ +Running Gradle task 'assembleDebug'... + +FAILURE: Build failed with an exception. + +* What went wrong: +Execution failed for task ':llama_sdk:configureCMakeDebug[arm64-v8a]'. +> [CXX1429] error when building with cmake using /Users/friday/.pub-cache/git/lcpp-7c2f8423e87781859acc514cd0aa36554f423163/android/CMakeLists.txt: -- The C compiler identification is Clang 18.0.1 + -- The CXX compiler identification is Clang 18.0.1 + -- Detecting C compiler ABI info + -- Detecting C compiler ABI info - done + -- Check for working C compiler: /Users/friday/Library/Android/sdk/ndk/27.0.12077973/toolchains/llvm/prebuilt/darwin-x86_64/bin/clang - skipped + -- Detecting C compile features + -- Detecting C compile features - done + -- Detecting CXX compiler ABI info + -- Detecting CXX compiler ABI info - done + -- Check for working CXX compiler: /Users/friday/Library/Android/sdk/ndk/27.0.12077973/toolchains/llvm/prebuilt/darwin-x86_64/bin/clang++ - skipped + -- Detecting CXX compile features + -- Detecting CXX compile features - done + -- Configuring incomplete, errors occurred! + See also "/Users/friday/.pub-cache/git/lcpp-7c2f8423e87781859acc514cd0aa36554f423163/android/.cxx/Debug/1y5h19dr/arm64-v8a/CMakeFiles/CMakeOutput.log". + + C++ build system [configure] failed while executing: + /Users/friday/Library/Android/sdk/cmake/3.22.1/bin/cmake \ + -H/Users/friday/.pub-cache/git/lcpp-7c2f8423e87781859acc514cd0aa36554f423163/android \ + -DCMAKE_SYSTEM_NAME=Android \ + -DCMAKE_EXPORT_COMPILE_COMMANDS=ON \ + -DCMAKE_SYSTEM_VERSION=23 \ + -DANDROID_PLATFORM=android-23 \ + -DANDROID_ABI=arm64-v8a \ + -DCMAKE_ANDROID_ARCH_ABI=arm64-v8a \ + -DANDROID_NDK=/Users/friday/Library/Android/sdk/ndk/27.0.12077973 \ + -DCMAKE_ANDROID_NDK=/Users/friday/Library/Android/sdk/ndk/27.0.12077973 \ + -DCMAKE_TOOLCHAIN_FILE=/Users/friday/Library/Android/sdk/ndk/27.0.12077973/build/cmake/android.toolchain.cmake \ + -DCMAKE_MAKE_PROGRAM=/Users/friday/Library/Android/sdk/cmake/3.22.1/bin/ninja \ + -DCMAKE_LIBRARY_OUTPUT_DIRECTORY=/Users/friday/premithus/build/llama_sdk/intermediates/cxx/Debug/1y5h19dr/obj/arm64-v8a \ + -DCMAKE_RUNTIME_OUTPUT_DIRECTORY=/Users/friday/premithus/build/llama_sdk/intermediates/cxx/Debug/1y5h19dr/obj/arm64-v8a \ + -DCMAKE_BUILD_TYPE=Debug \ + -B/Users/friday/.pub-cache/git/lcpp-7c2f8423e87781859acc514cd0aa36554f423163/android/.cxx/Debug/1y5h19dr/arm64-v8a \ + -GNinja + from /Users/friday/.pub-cache/git/lcpp-7c2f8423e87781859acc514cd0aa36554f423163/android + CMake Error at CMakeLists.txt:15 (add_subdirectory): + The source directory + + /Users/friday/.pub-cache/git/lcpp-7c2f8423e87781859acc514cd0aa36554f423163/src/llama_cpp + + does not contain a CMakeLists.txt file. + + + CMake Error at CMakeLists.txt:17 (target_include_directories): + Cannot specify include directories for target "llama" which is not built by + this project. + + + CMake Error at CMakeLists.txt:23 (target_sources): + Cannot specify sources for target "llama" which is not built by this + project. + + + CMake Error at CMakeLists.txt:30 (target_compile_options): + Cannot specify compile options for target "llama" which is not built by + this project. + + + CMake Error at CMakeLists.txt:39 (target_link_options): + Cannot specify link options for target "llama" which is not built by this + project. + + + CMake Error at CMakeLists.txt:49 (target_compile_options): + Cannot specify compile options for target "llama" which is not built by + this project. : com.android.ide.common.process.ProcessException: -- The C compiler identification is Clang 18.0.1 + -- The CXX compiler identification is Clang 18.0.1 + -- Detecting C compiler ABI info + -- Detecting C compiler ABI info - done + -- Check for working C compiler: /Users/friday/Library/Android/sdk/ndk/27.0.12077973/toolchains/llvm/prebuilt/darwin-x86_64/bin/clang - skipped + -- Detecting C compile features + -- Detecting C compile features - done + -- Detecting CXX compiler ABI info + -- Detecting CXX compiler ABI info - done + -- Check for working CXX compiler: /Users/friday/Library/Android/sdk/ndk/27.0.12077973/toolchains/llvm/prebuilt/darwin-x86_64/bin/clang++ - skipped + -- Detecting CXX compile features + -- Detecting CXX compile features - done + -- Configuring incomplete, errors occurred! + See also "/Users/friday/.pub-cache/git/lcpp-7c2f8423e87781859acc514cd0aa36554f423163/android/.cxx/Debug/1y5h19dr/arm64-v8a/CMakeFiles/CMakeOutput.log". + + C++ build system [configure] failed while executing: + /Users/friday/Library/Android/sdk/cmake/3.22.1/bin/cmake \ + -H/Users/friday/.pub-cache/git/lcpp-7c2f8423e87781859acc514cd0aa36554f423163/android \ + -DCMAKE_SYSTEM_NAME=Android \ + -DCMAKE_EXPORT_COMPILE_COMMANDS=ON \ + -DCMAKE_SYSTEM_VERSION=23 \ + -DANDROID_PLATFORM=android-23 \ + -DANDROID_ABI=arm64-v8a \ + -DCMAKE_ANDROID_ARCH_ABI=arm64-v8a \ + -DANDROID_NDK=/Users/friday/Library/Android/sdk/ndk/27.0.12077973 \ + -DCMAKE_ANDROID_NDK=/Users/friday/Library/Android/sdk/ndk/27.0.12077973 \ + -DCMAKE_TOOLCHAIN_FILE=/Users/friday/Library/Android/sdk/ndk/27.0.12077973/build/cmake/android.toolchain.cmake \ + -DCMAKE_MAKE_PROGRAM=/Users/friday/Library/Android/sdk/cmake/3.22.1/bin/ninja \ + -DCMAKE_LIBRARY_OUTPUT_DIRECTORY=/Users/friday/premithus/build/llama_sdk/intermediates/cxx/Debug/1y5h19dr/obj/arm64-v8a \ + -DCMAKE_RUNTIME_OUTPUT_DIRECTORY=/Users/friday/premithus/build/llama_sdk/intermediates/cxx/Debug/1y5h19dr/obj/arm64-v8a \ + -DCMAKE_BUILD_TYPE=Debug \ + -B/Users/friday/.pub-cache/git/lcpp-7c2f8423e87781859acc514cd0aa36554f423163/android/.cxx/Debug/1y5h19dr/arm64-v8a \ + -GNinja + from /Users/friday/.pub-cache/git/lcpp-7c2f8423e87781859acc514cd0aa36554f423163/android + CMake Error at CMakeLists.txt:15 (add_subdirectory): + The source directory + + /Users/friday/.pub-cache/git/lcpp-7c2f8423e87781859acc514cd0aa36554f423163/src/llama_cpp + + does not contain a CMakeLists.txt file. + + + CMake Error at CMakeLists.txt:17 (target_include_directories): + Cannot specify include directories for target "llama" which is not built by + this project. + + + CMake Error at CMakeLists.txt:23 (target_sources): + Cannot specify sources for target "llama" which is not built by this + project. + + + CMake Error at CMakeLists.txt:30 (target_compile_options): + Cannot specify compile options for target "llama" which is not built by + this project. + + + CMake Error at CMakeLists.txt:39 (target_link_options): + Cannot specify link options for target "llama" which is not built by this + project. + + + CMake Error at CMakeLists.txt:49 (target_compile_options): + Cannot specify compile options for target "llama" which is not built by + this project. + at com.android.build.gradle.internal.cxx.process.ExecuteProcessKt.execute(ExecuteProcess.kt:288) + at com.android.build.gradle.internal.cxx.process.ExecuteProcessKt$executeProcess$1.invoke(ExecuteProcess.kt:108) + at com.android.build.gradle.internal.cxx.process.ExecuteProcessKt$executeProcess$1.invoke(ExecuteProcess.kt:106) + at com.android.build.gradle.internal.cxx.timing.TimingEnvironmentKt.time(TimingEnvironment.kt:32) + at com.android.build.gradle.internal.cxx.process.ExecuteProcessKt.executeProcess(ExecuteProcess.kt:106) + at com.android.build.gradle.internal.cxx.process.ExecuteProcessKt.executeProcess$default(ExecuteProcess.kt:85) + at com.android.build.gradle.tasks.CmakeQueryMetadataGenerator.executeProcess(CmakeFileApiMetadataGenerator.kt:59) + at com.android.build.gradle.tasks.ExternalNativeJsonGenerator$configureOneAbi$1$1$3.invoke(ExternalNativeJsonGenerator.kt:247) + at com.android.build.gradle.tasks.ExternalNativeJsonGenerator$configureOneAbi$1$1$3.invoke(ExternalNativeJsonGenerator.kt:247) + at com.android.build.gradle.internal.cxx.timing.TimingEnvironmentKt.time(TimingEnvironment.kt:32) + at com.android.build.gradle.tasks.ExternalNativeJsonGenerator.configureOneAbi(ExternalNativeJsonGenerator.kt:247) + at com.android.build.gradle.tasks.ExternalNativeJsonGenerator.configure(ExternalNativeJsonGenerator.kt:113) + at com.android.build.gradle.tasks.ExternalNativeBuildJsonTask.doTaskAction(ExternalNativeBuildJsonTask.kt:89) + at com.android.build.gradle.internal.tasks.UnsafeOutputsTask$taskAction$$inlined$recordTaskAction$1.invoke(BaseTask.kt:59) + at com.android.build.gradle.internal.tasks.Blocks.recordSpan(Blocks.java:51) + at com.android.build.gradle.internal.tasks.UnsafeOutputsTask.taskAction(UnsafeOutputsTask.kt:81) + at java.base/jdk.internal.reflect.DirectMethodHandleAccessor.invoke(Unknown Source) + at java.base/java.lang.reflect.Method.invoke(Unknown Source) + at org.gradle.internal.reflect.JavaMethod.invoke(JavaMethod.java:125) + at org.gradle.api.internal.project.taskfactory.StandardTaskAction.doExecute(StandardTaskAction.java:58) + at org.gradle.api.internal.project.taskfactory.StandardTaskAction.execute(StandardTaskAction.java:51) + at org.gradle.api.internal.project.taskfactory.StandardTaskAction.execute(StandardTaskAction.java:29) + at org.gradle.api.internal.tasks.execution.TaskExecution$3.run(TaskExecution.java:244) + at org.gradle.internal.operations.DefaultBuildOperationRunner$1.execute(DefaultBuildOperationRunner.java:30) + at org.gradle.internal.operations.DefaultBuildOperationRunner$1.execute(DefaultBuildOperationRunner.java:27) + at org.gradle.internal.operations.DefaultBuildOperationRunner$2.execute(DefaultBuildOperationRunner.java:67) + at org.gradle.internal.operations.DefaultBuildOperationRunner$2.execute(DefaultBuildOperationRunner.java:60) + at org.gradle.internal.operations.DefaultBuildOperationRunner.execute(DefaultBuildOperationRunner.java:167) + at org.gradle.internal.operations.DefaultBuildOperationRunner.execute(DefaultBuildOperationRunner.java:60) + at org.gradle.internal.operations.DefaultBuildOperationRunner.run(DefaultBuildOperationRunner.java:48) + at org.gradle.api.internal.tasks.execution.TaskExecution.executeAction(TaskExecution.java:229) + at org.gradle.api.internal.tasks.execution.TaskExecution.executeActions(TaskExecution.java:212) + at org.gradle.api.internal.tasks.execution.TaskExecution.executeWithPreviousOutputFiles(TaskExecution.java:195) + at org.gradle.api.internal.tasks.execution.TaskExecution.execute(TaskExecution.java:162) + at org.gradle.internal.execution.steps.ExecuteStep.executeInternal(ExecuteStep.java:105) + at org.gradle.internal.execution.steps.ExecuteStep.access$000(ExecuteStep.java:44) + at org.gradle.internal.execution.steps.ExecuteStep$1.call(ExecuteStep.java:59) + at org.gradle.internal.execution.steps.ExecuteStep$1.call(ExecuteStep.java:56) + at org.gradle.internal.operations.DefaultBuildOperationRunner$CallableBuildOperationWorker.execute(DefaultBuildOperationRunner.java:210) + at org.gradle.internal.operations.DefaultBuildOperationRunner$CallableBuildOperationWorker.execute(DefaultBuildOperationRunner.java:205) + at org.gradle.internal.operations.DefaultBuildOperationRunner$2.execute(DefaultBuildOperationRunner.java:67) + at org.gradle.internal.operations.DefaultBuildOperationRunner$2.execute(DefaultBuildOperationRunner.java:60) + at org.gradle.internal.operations.DefaultBuildOperationRunner.execute(DefaultBuildOperationRunner.java:167) + at org.gradle.internal.operations.DefaultBuildOperationRunner.execute(DefaultBuildOperationRunner.java:60) + at org.gradle.internal.operations.DefaultBuildOperationRunner.call(DefaultBuildOperationRunner.java:54) + at org.gradle.internal.execution.steps.ExecuteStep.execute(ExecuteStep.java:56) + at org.gradle.internal.execution.steps.ExecuteStep.execute(ExecuteStep.java:44) + at org.gradle.internal.execution.steps.CancelExecutionStep.execute(CancelExecutionStep.java:42) + at org.gradle.internal.execution.steps.TimeoutStep.executeWithoutTimeout(TimeoutStep.java:75) + at org.gradle.internal.execution.steps.TimeoutStep.execute(TimeoutStep.java:55) + at org.gradle.internal.execution.steps.PreCreateOutputParentsStep.execute(PreCreateOutputParentsStep.java:50) + at org.gradle.internal.execution.steps.PreCreateOutputParentsStep.execute(PreCreateOutputParentsStep.java:28) + at org.gradle.internal.execution.steps.RemovePreviousOutputsStep.execute(RemovePreviousOutputsStep.java:67) + at org.gradle.internal.execution.steps.RemovePreviousOutputsStep.execute(RemovePreviousOutputsStep.java:37) + at org.gradle.internal.execution.steps.BroadcastChangingOutputsStep.execute(BroadcastChangingOutputsStep.java:61) + at org.gradle.internal.execution.steps.BroadcastChangingOutputsStep.execute(BroadcastChangingOutputsStep.java:26) + at org.gradle.internal.execution.steps.CaptureOutputsAfterExecutionStep.execute(CaptureOutputsAfterExecutionStep.java:69) + at org.gradle.internal.execution.steps.CaptureOutputsAfterExecutionStep.execute(CaptureOutputsAfterExecutionStep.java:46) + at org.gradle.internal.execution.steps.ResolveInputChangesStep.execute(ResolveInputChangesStep.java:40) + at org.gradle.internal.execution.steps.ResolveInputChangesStep.execute(ResolveInputChangesStep.java:29) + at org.gradle.internal.execution.steps.BuildCacheStep.executeWithoutCache(BuildCacheStep.java:189) + at org.gradle.internal.execution.steps.BuildCacheStep.lambda$execute$1(BuildCacheStep.java:75) + at org.gradle.internal.Either$Right.fold(Either.java:175) + at org.gradle.internal.execution.caching.CachingState.fold(CachingState.java:62) + at org.gradle.internal.execution.steps.BuildCacheStep.execute(BuildCacheStep.java:73) + at org.gradle.internal.execution.steps.BuildCacheStep.execute(BuildCacheStep.java:48) + at org.gradle.internal.execution.steps.StoreExecutionStateStep.execute(StoreExecutionStateStep.java:46) + at org.gradle.internal.execution.steps.StoreExecutionStateStep.execute(StoreExecutionStateStep.java:35) + at org.gradle.internal.execution.steps.SkipUpToDateStep.executeBecause(SkipUpToDateStep.java:75) + at org.gradle.internal.execution.steps.SkipUpToDateStep.lambda$execute$2(SkipUpToDateStep.java:53) + at java.base/java.util.Optional.orElseGet(Unknown Source) + at org.gradle.internal.execution.steps.SkipUpToDateStep.execute(SkipUpToDateStep.java:53) + at org.gradle.internal.execution.steps.SkipUpToDateStep.execute(SkipUpToDateStep.java:35) + at org.gradle.internal.execution.steps.legacy.MarkSnapshottingInputsFinishedStep.execute(MarkSnapshottingInputsFinishedStep.java:37) + at org.gradle.internal.execution.steps.legacy.MarkSnapshottingInputsFinishedStep.execute(MarkSnapshottingInputsFinishedStep.java:27) + at org.gradle.internal.execution.steps.ResolveIncrementalCachingStateStep.executeDelegate(ResolveIncrementalCachingStateStep.java:49) + at org.gradle.internal.execution.steps.ResolveIncrementalCachingStateStep.executeDelegate(ResolveIncrementalCachingStateStep.java:27) + at org.gradle.internal.execution.steps.AbstractResolveCachingStateStep.execute(AbstractResolveCachingStateStep.java:71) + at org.gradle.internal.execution.steps.AbstractResolveCachingStateStep.execute(AbstractResolveCachingStateStep.java:39) + at org.gradle.internal.execution.steps.ResolveChangesStep.execute(ResolveChangesStep.java:65) + at org.gradle.internal.execution.steps.ResolveChangesStep.execute(ResolveChangesStep.java:36) + at org.gradle.internal.execution.steps.ValidateStep.execute(ValidateStep.java:107) + at org.gradle.internal.execution.steps.ValidateStep.execute(ValidateStep.java:56) + at org.gradle.internal.execution.steps.AbstractCaptureStateBeforeExecutionStep.execute(AbstractCaptureStateBeforeExecutionStep.java:64) + at org.gradle.internal.execution.steps.AbstractCaptureStateBeforeExecutionStep.execute(AbstractCaptureStateBeforeExecutionStep.java:43) + at org.gradle.internal.execution.steps.AbstractSkipEmptyWorkStep.executeWithNonEmptySources(AbstractSkipEmptyWorkStep.java:125) + at org.gradle.internal.execution.steps.AbstractSkipEmptyWorkStep.execute(AbstractSkipEmptyWorkStep.java:56) + at org.gradle.internal.execution.steps.AbstractSkipEmptyWorkStep.execute(AbstractSkipEmptyWorkStep.java:36) + at org.gradle.internal.execution.steps.legacy.MarkSnapshottingInputsStartedStep.execute(MarkSnapshottingInputsStartedStep.java:38) + at org.gradle.internal.execution.steps.LoadPreviousExecutionStateStep.execute(LoadPreviousExecutionStateStep.java:36) + at org.gradle.internal.execution.steps.LoadPreviousExecutionStateStep.execute(LoadPreviousExecutionStateStep.java:23) + at org.gradle.internal.execution.steps.HandleStaleOutputsStep.execute(HandleStaleOutputsStep.java:75) + at org.gradle.internal.execution.steps.HandleStaleOutputsStep.execute(HandleStaleOutputsStep.java:41) + at org.gradle.internal.execution.steps.AssignMutableWorkspaceStep.lambda$execute$0(AssignMutableWorkspaceStep.java:35) + at org.gradle.api.internal.tasks.execution.TaskExecution$4.withWorkspace(TaskExecution.java:289) + at org.gradle.internal.execution.steps.AssignMutableWorkspaceStep.execute(AssignMutableWorkspaceStep.java:31) + at org.gradle.internal.execution.steps.AssignMutableWorkspaceStep.execute(AssignMutableWorkspaceStep.java:22) + at org.gradle.internal.execution.steps.ChoosePipelineStep.execute(ChoosePipelineStep.java:40) + at org.gradle.internal.execution.steps.ChoosePipelineStep.execute(ChoosePipelineStep.java:23) + at org.gradle.internal.execution.steps.ExecuteWorkBuildOperationFiringStep.lambda$execute$2(ExecuteWorkBuildOperationFiringStep.java:67) + at java.base/java.util.Optional.orElseGet(Unknown Source) + at org.gradle.internal.execution.steps.ExecuteWorkBuildOperationFiringStep.execute(ExecuteWorkBuildOperationFiringStep.java:67) + at org.gradle.internal.execution.steps.ExecuteWorkBuildOperationFiringStep.execute(ExecuteWorkBuildOperationFiringStep.java:39) + at org.gradle.internal.execution.steps.IdentityCacheStep.execute(IdentityCacheStep.java:46) + at org.gradle.internal.execution.steps.IdentityCacheStep.execute(IdentityCacheStep.java:34) + at org.gradle.internal.execution.steps.IdentifyStep.execute(IdentifyStep.java:48) + at org.gradle.internal.execution.steps.IdentifyStep.execute(IdentifyStep.java:35) + at org.gradle.internal.execution.impl.DefaultExecutionEngine$1.execute(DefaultExecutionEngine.java:64) + at org.gradle.api.internal.tasks.execution.ExecuteActionsTaskExecuter.executeIfValid(ExecuteActionsTaskExecuter.java:127) + at org.gradle.api.internal.tasks.execution.ExecuteActionsTaskExecuter.execute(ExecuteActionsTaskExecuter.java:116) + at org.gradle.api.internal.tasks.execution.ProblemsTaskPathTrackingTaskExecuter.execute(ProblemsTaskPathTrackingTaskExecuter.java:41) + at org.gradle.api.internal.tasks.execution.FinalizePropertiesTaskExecuter.execute(FinalizePropertiesTaskExecuter.java:46) + at org.gradle.api.internal.tasks.execution.ResolveTaskExecutionModeExecuter.execute(ResolveTaskExecutionModeExecuter.java:51) + at org.gradle.api.internal.tasks.execution.SkipTaskWithNoActionsExecuter.execute(SkipTaskWithNoActionsExecuter.java:57) + at org.gradle.api.internal.tasks.execution.SkipOnlyIfTaskExecuter.execute(SkipOnlyIfTaskExecuter.java:74) + at org.gradle.api.internal.tasks.execution.CatchExceptionTaskExecuter.execute(CatchExceptionTaskExecuter.java:36) + at org.gradle.api.internal.tasks.execution.EventFiringTaskExecuter$1.executeTask(EventFiringTaskExecuter.java:77) + at org.gradle.api.internal.tasks.execution.EventFiringTaskExecuter$1.call(EventFiringTaskExecuter.java:55) + at org.gradle.api.internal.tasks.execution.EventFiringTaskExecuter$1.call(EventFiringTaskExecuter.java:52) + at org.gradle.internal.operations.DefaultBuildOperationRunner$CallableBuildOperationWorker.execute(DefaultBuildOperationRunner.java:210) + at org.gradle.internal.operations.DefaultBuildOperationRunner$CallableBuildOperationWorker.execute(DefaultBuildOperationRunner.java:205) + at org.gradle.internal.operations.DefaultBuildOperationRunner$2.execute(DefaultBuildOperationRunner.java:67) + at org.gradle.internal.operations.DefaultBuildOperationRunner$2.execute(DefaultBuildOperationRunner.java:60) + at org.gradle.internal.operations.DefaultBuildOperationRunner.execute(DefaultBuildOperationRunner.java:167) + at org.gradle.internal.operations.DefaultBuildOperationRunner.execute(DefaultBuildOperationRunner.java:60) + at org.gradle.internal.operations.DefaultBuildOperationRunner.call(DefaultBuildOperationRunner.java:54) + at org.gradle.api.internal.tasks.execution.EventFiringTaskExecuter.execute(EventFiringTaskExecuter.java:52) + at org.gradle.execution.plan.LocalTaskNodeExecutor.execute(LocalTaskNodeExecutor.java:42) + at org.gradle.execution.taskgraph.DefaultTaskExecutionGraph$InvokeNodeExecutorsAction.execute(DefaultTaskExecutionGraph.java:331) + at org.gradle.execution.taskgraph.DefaultTaskExecutionGraph$InvokeNodeExecutorsAction.execute(DefaultTaskExecutionGraph.java:318) + at org.gradle.execution.taskgraph.DefaultTaskExecutionGraph$BuildOperationAwareExecutionAction.lambda$execute$0(DefaultTaskExecutionGraph.java:314) + at org.gradle.internal.operations.CurrentBuildOperationRef.with(CurrentBuildOperationRef.java:85) + at org.gradle.execution.taskgraph.DefaultTaskExecutionGraph$BuildOperationAwareExecutionAction.execute(DefaultTaskExecutionGraph.java:314) + at org.gradle.execution.taskgraph.DefaultTaskExecutionGraph$BuildOperationAwareExecutionAction.execute(DefaultTaskExecutionGraph.java:303) + at org.gradle.execution.plan.DefaultPlanExecutor$ExecutorWorker.execute(DefaultPlanExecutor.java:459) + at org.gradle.execution.plan.DefaultPlanExecutor$ExecutorWorker.run(DefaultPlanExecutor.java:376) + at org.gradle.internal.concurrent.ExecutorPolicy$CatchAndRecordFailures.onExecute(ExecutorPolicy.java:64) + at org.gradle.internal.concurrent.AbstractManagedExecutor$1.run(AbstractManagedExecutor.java:48) + at java.base/java.util.concurrent.ThreadPoolExecutor.runWorker(Unknown Source) + at java.base/java.util.concurrent.ThreadPoolExecutor$Worker.run(Unknown Source) + at java.base/java.lang.Thread.run(Unknown Source) + Caused by: com.android.ide.common.process.ProcessException: Error while executing process /Users/friday/Library/Android/sdk/cmake/3.22.1/bin/cmake with arguments {-H/Users/friday/.pub-cache/git/lcpp-7c2f8423e87781859acc514cd0aa36554f423163/android -DCMAKE_SYSTEM_NAME=Android -DCMAKE_EXPORT_COMPILE_COMMANDS=ON -DCMAKE_SYSTEM_VERSION=23 -DANDROID_PLATFORM=android-23 -DANDROID_ABI=arm64-v8a -DCMAKE_ANDROID_ARCH_ABI=arm64-v8a -DANDROID_NDK=/Users/friday/Library/Android/sdk/ndk/27.0.12077973 -DCMAKE_ANDROID_NDK=/Users/friday/Library/Android/sdk/ndk/27.0.12077973 -DCMAKE_TOOLCHAIN_FILE=/Users/friday/Library/Android/sdk/ndk/27.0.12077973/build/cmake/android.toolchain.cmake -DCMAKE_MAKE_PROGRAM=/Users/friday/Library/Android/sdk/cmake/3.22.1/bin/ninja -DCMAKE_LIBRARY_OUTPUT_DIRECTORY=/Users/friday/premithus/build/llama_sdk/intermediates/cxx/Debug/1y5h19dr/obj/arm64-v8a -DCMAKE_RUNTIME_OUTPUT_DIRECTORY=/Users/friday/premithus/build/llama_sdk/intermediates/cxx/Debug/1y5h19dr/obj/arm64-v8a -DCMAKE_BUILD_TYPE=Debug -B/Users/friday/.pub-cache/git/lcpp-7c2f8423e87781859acc514cd0aa36554f423163/android/.cxx/Debug/1y5h19dr/arm64-v8a -GNinja} + at com.android.build.gradle.internal.process.GradleProcessResult.buildProcessException(GradleProcessResult.java:73) + at com.android.build.gradle.internal.process.GradleProcessResult.assertNormalExitValue(GradleProcessResult.java:48) + at com.android.build.gradle.internal.cxx.process.ExecuteProcessKt.execute(ExecuteProcess.kt:277) + ... 140 more + Caused by: org.gradle.process.internal.ExecException: Process 'command '/Users/friday/Library/Android/sdk/cmake/3.22.1/bin/cmake'' finished with non-zero exit value 1 + at org.gradle.process.internal.DefaultExecHandle$ExecResultImpl.assertNormalExitValue(DefaultExecHandle.java:442) + at com.android.build.gradle.internal.process.GradleProcessResult.assertNormalExitValue(GradleProcessResult.java:46) + ... 141 more + + +* Try: +> Run with --stacktrace option to get the stack trace. +> Run with --info or --debug option to get more log output. +> Run with --scan to get full insights. +> Get more help at https://help.gradle.org. + +BUILD FAILED in 2s +Running Gradle task 'assembleDebug'... 2,115ms +Gradle task assembleDebug failed with exit code 1 diff --git a/convert_bert.py b/convert_bert.py new file mode 100644 index 0000000000000000000000000000000000000000..ad5a27e3096fb36b77b123cb599475521384ca47 --- /dev/null +++ b/convert_bert.py @@ -0,0 +1,42 @@ +import tensorflow as tf +from transformers import AutoTokenizer, TFAutoModelForSequenceClassification +import os + +model_name = "mrm8488/bert-tiny-finetuned-sms-spam-detection" + +print("Loading model and tokenizer...") +tokenizer = AutoTokenizer.from_pretrained(model_name) +model = TFAutoModelForSequenceClassification.from_pretrained(model_name, from_pt=True) + +print("Exporting vocab...") +os.makedirs("models", exist_ok=True) +with open("models/vocab.txt", "w", encoding="utf-8") as f: + for token, index in sorted(tokenizer.get_vocab().items(), key=lambda x: x[1]): + f.write(f"{token}\n") + +print("Tracing model for TFLite conversion...") +MAX_SEQ_LEN = 128 + +callable_model = tf.function( + lambda input_ids, attention_mask: model(input_ids=input_ids, attention_mask=attention_mask, training=False) +) + +concrete_func = callable_model.get_concrete_function( + tf.TensorSpec([1, MAX_SEQ_LEN], tf.int32, name="input_ids"), + tf.TensorSpec([1, MAX_SEQ_LEN], tf.int32, name="attention_mask") +) + +print("Converting to TFLite...") +converter = tf.lite.TFLiteConverter.from_concrete_functions([concrete_func]) +converter.optimizations = [tf.lite.Optimize.DEFAULT] +converter.target_spec.supported_ops = [ + tf.lite.OpsSet.TFLITE_BUILTINS, + tf.lite.OpsSet.SELECT_TF_OPS +] + +tflite_model = converter.convert() + +with open("models/scam_classifier.tflite", "wb") as f: + f.write(tflite_model) + +print("Done! Model saved to models/scam_classifier.tflite") diff --git a/demo_script_v0.0.2.md b/demo_script_v0.0.2.md new file mode 100644 index 0000000000000000000000000000000000000000..c7c862acd248044ed1370a7ef1715ebd58708e52 --- /dev/null +++ b/demo_script_v0.0.2.md @@ -0,0 +1,28 @@ +# Premithius V0.0.2 Demo Script + +**Theme:** India-First On-Device AI Security | Zero LLM | ARMadillo Architecture + +## Demo 1: The Zero-Day Scam (Vector Engine) +**Scenario:** A completely new scam variant that isn't in any blacklist yet. +1. Send SMS to emulator: `adb shell am broadcast -a android.provider.Telephony.SMS_RECEIVED -d "SMS_BODY:Urgent! Your HDFC acct is blocked. Update KYC immediately via http://hdfc.kyc-update-xyz.in"` +2. **Observe:** Premithius overlay appears instantly (under 50ms). +3. **Explanation:** "Unlike cloud antiviruses that need updates, our `sqlite-vec` engine running locally instantly recognized the semantic meaning of 'urgent KYC update' bypassing traditional filters. It never left the device." + +## Demo 2: The UPI Rs. 1 Collect Fraud (India Threat Pack) +**Scenario:** The classic OLX/Marketplace fraud. +1. Send SMS: `adb shell am broadcast -a android.provider.Telephony.SMS_RECEIVED -d "SMS_BODY:Dear Customer, Rs 12,500 has been credited... To receive money, please authorize Rs. 1 collect request from VPA: scammer@ybl"` +2. **Observe:** Kavacha Firewall blocks it natively. +3. **Explanation:** "Our Layer 1 India Threat Pack specifically targets regional payment infrastructure. We catch the ₹1 collect trick natively before it hits complex models." + +## Demo 3: Data Shield & System Visibility +1. Open the Premithius App -> Navigate to **Data Shield Insights** +2. **Observe:** Plain English translations of complex OS data (e.g., "TikTok sent 340 MB of data between 2am–4am last night"). +3. **Explanation:** "Instead of obscure permission screens, we translate system telemetry into human-readable privacy stories. The home screen widget surfaces these anomalies effortlessly." + +## Demo 4: Aadhaar/PAN Outgoing Intercept (Keyboard) +**Scenario:** User typing their Aadhaar number to a stranger on WhatsApp. +1. Open any chat app. +2. Select Premithius Keyboard. +3. Type: `Mera Aadhaar 1234 5678 9012 hai` and hit Enter/Send. +4. **Observe:** Warning overlay/snack bar: "Wait! You are about to send a sensitive ID." +5. **Explanation:** "Our keyboard is the final line of defense. It detects outbound PII like Aadhaar or PAN on the edge, warning the user *before* it ends up on a scammer's server." diff --git a/hf_space b/hf_space new file mode 160000 index 0000000000000000000000000000000000000000..ca0c577efb6417cf89c554b17f3c9b8af9a3fa42 --- /dev/null +++ b/hf_space @@ -0,0 +1 @@ +Subproject commit ca0c577efb6417cf89c554b17f3c9b8af9a3fa42 diff --git a/index.html b/index.html new file mode 100644 index 0000000000000000000000000000000000000000..b0c4b3666032a737f3903db53e6a8a9272483e28 --- /dev/null +++ b/index.html @@ -0,0 +1,19 @@ + + + + + + My static Space + + + +
+

Welcome to your static Space!

+

You can modify this app directly by editing index.html in the Files and versions tab.

+

+ Also don't forget to check the + Spaces documentation. +

+
+ + diff --git a/ios/.gitignore b/ios/.gitignore new file mode 100644 index 0000000000000000000000000000000000000000..7a7f9873ad7dceb4dc17087fb06c800fa0191376 --- /dev/null +++ b/ios/.gitignore @@ -0,0 +1,34 @@ +**/dgph +*.mode1v3 +*.mode2v3 +*.moved-aside +*.pbxuser +*.perspectivev3 +**/*sync/ +.sconsign.dblite +.tags* +**/.vagrant/ +**/DerivedData/ +Icon? +**/Pods/ +**/.symlinks/ +profile +xcuserdata +**/.generated/ +Flutter/App.framework +Flutter/Flutter.framework +Flutter/Flutter.podspec +Flutter/Generated.xcconfig +Flutter/ephemeral/ +Flutter/app.flx +Flutter/app.zip +Flutter/flutter_assets/ +Flutter/flutter_export_environment.sh +ServiceDefinitions.json +Runner/GeneratedPluginRegistrant.* + +# Exceptions to above rules. +!default.mode1v3 +!default.mode2v3 +!default.pbxuser +!default.perspectivev3 diff --git a/ios/Flutter/AppFrameworkInfo.plist b/ios/Flutter/AppFrameworkInfo.plist new file mode 100644 index 0000000000000000000000000000000000000000..391a902b2bebe1a3df1b090312fd85029dd99308 --- /dev/null +++ b/ios/Flutter/AppFrameworkInfo.plist @@ -0,0 +1,24 @@ + + + + + CFBundleDevelopmentRegion + en + CFBundleExecutable + App + CFBundleIdentifier + io.flutter.flutter.app + CFBundleInfoDictionaryVersion + 6.0 + CFBundleName + App + CFBundlePackageType + FMWK + CFBundleShortVersionString + 1.0 + CFBundleSignature + ???? + CFBundleVersion + 1.0 + + diff --git a/ios/Flutter/Debug.xcconfig b/ios/Flutter/Debug.xcconfig new file mode 100644 index 0000000000000000000000000000000000000000..ec97fc6f30212d34d53ab17751bcabdfab1891d4 --- /dev/null +++ b/ios/Flutter/Debug.xcconfig @@ -0,0 +1,2 @@ +#include? "Pods/Target Support Files/Pods-Runner/Pods-Runner.debug.xcconfig" +#include "Generated.xcconfig" diff --git a/ios/Flutter/Release.xcconfig b/ios/Flutter/Release.xcconfig new file mode 100644 index 0000000000000000000000000000000000000000..c4855bfe2000b73c8a50783b40073676021cbb68 --- /dev/null +++ b/ios/Flutter/Release.xcconfig @@ -0,0 +1,2 @@ +#include? "Pods/Target Support Files/Pods-Runner/Pods-Runner.release.xcconfig" +#include "Generated.xcconfig" diff --git a/ios/Podfile b/ios/Podfile new file mode 100644 index 0000000000000000000000000000000000000000..620e46eba607b0032bd7eee691b0f40df44b4c5d --- /dev/null +++ b/ios/Podfile @@ -0,0 +1,43 @@ +# Uncomment this line to define a global platform for your project +# platform :ios, '13.0' + +# CocoaPods analytics sends network stats synchronously affecting flutter build latency. +ENV['COCOAPODS_DISABLE_STATS'] = 'true' + +project 'Runner', { + 'Debug' => :debug, + 'Profile' => :release, + 'Release' => :release, +} + +def flutter_root + generated_xcode_build_settings_path = File.expand_path(File.join('..', 'Flutter', 'Generated.xcconfig'), __FILE__) + unless File.exist?(generated_xcode_build_settings_path) + raise "#{generated_xcode_build_settings_path} must exist. If you're running pod install manually, make sure flutter pub get is executed first" + end + + File.foreach(generated_xcode_build_settings_path) do |line| + matches = line.match(/FLUTTER_ROOT\=(.*)/) + return matches[1].strip if matches + end + raise "FLUTTER_ROOT not found in #{generated_xcode_build_settings_path}. Try deleting Generated.xcconfig, then run flutter pub get" +end + +require File.expand_path(File.join('packages', 'flutter_tools', 'bin', 'podhelper'), flutter_root) + +flutter_ios_podfile_setup + +target 'Runner' do + use_frameworks! + + flutter_install_all_ios_pods File.dirname(File.realpath(__FILE__)) + target 'RunnerTests' do + inherit! :search_paths + end +end + +post_install do |installer| + installer.pods_project.targets.each do |target| + flutter_additional_ios_build_settings(target) + end +end diff --git a/ios/Runner.xcodeproj/project.pbxproj b/ios/Runner.xcodeproj/project.pbxproj new file mode 100644 index 0000000000000000000000000000000000000000..fbefcf2afea1f43ba8c7334df6fb75b5e0af1d89 --- /dev/null +++ b/ios/Runner.xcodeproj/project.pbxproj @@ -0,0 +1,623 @@ +// !$*UTF8*$! +{ + archiveVersion = 1; + classes = { + }; + objectVersion = 54; + objects = { + +/* Begin PBXBuildFile section */ + 1498D2341E8E89220040F4C2 /* GeneratedPluginRegistrant.m in Sources */ = {isa = PBXBuildFile; fileRef = 1498D2331E8E89220040F4C2 /* GeneratedPluginRegistrant.m */; }; + 331C808B294A63AB00263BE5 /* RunnerTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 331C807B294A618700263BE5 /* RunnerTests.swift */; }; + 3B3967161E833CAA004F5970 /* AppFrameworkInfo.plist in Resources */ = {isa = PBXBuildFile; fileRef = 3B3967151E833CAA004F5970 /* AppFrameworkInfo.plist */; }; + 74858FAF1ED2DC5600515810 /* AppDelegate.swift in Sources */ = {isa = PBXBuildFile; fileRef = 74858FAE1ED2DC5600515810 /* AppDelegate.swift */; }; + 7884E8682EC3CC0700C636F2 /* SceneDelegate.swift in Sources */ = {isa = PBXBuildFile; fileRef = 7884E8672EC3CC0400C636F2 /* SceneDelegate.swift */; }; + 97C146FC1CF9000F007C117D /* Main.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = 97C146FA1CF9000F007C117D /* Main.storyboard */; }; + 97C146FE1CF9000F007C117D /* Assets.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = 97C146FD1CF9000F007C117D /* Assets.xcassets */; }; + 97C147011CF9000F007C117D /* LaunchScreen.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = 97C146FF1CF9000F007C117D /* LaunchScreen.storyboard */; }; +/* End PBXBuildFile section */ + +/* Begin PBXContainerItemProxy section */ + 331C8085294A63A400263BE5 /* PBXContainerItemProxy */ = { + isa = PBXContainerItemProxy; + containerPortal = 97C146E61CF9000F007C117D /* Project object */; + proxyType = 1; + remoteGlobalIDString = 97C146ED1CF9000F007C117D; + remoteInfo = Runner; + }; +/* End PBXContainerItemProxy section */ + +/* Begin PBXCopyFilesBuildPhase section */ + 9705A1C41CF9048500538489 /* Embed Frameworks */ = { + isa = PBXCopyFilesBuildPhase; + buildActionMask = 2147483647; + dstPath = ""; + dstSubfolderSpec = 10; + files = ( + ); + name = "Embed Frameworks"; + runOnlyForDeploymentPostprocessing = 0; + }; +/* End PBXCopyFilesBuildPhase section */ + +/* Begin PBXFileReference section */ + 1498D2321E8E86230040F4C2 /* GeneratedPluginRegistrant.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = GeneratedPluginRegistrant.h; sourceTree = ""; }; + 1498D2331E8E89220040F4C2 /* GeneratedPluginRegistrant.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = GeneratedPluginRegistrant.m; sourceTree = ""; }; + 331C807B294A618700263BE5 /* RunnerTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = RunnerTests.swift; sourceTree = ""; }; + 331C8081294A63A400263BE5 /* RunnerTests.xctest */ = {isa = PBXFileReference; explicitFileType = wrapper.cfbundle; includeInIndex = 0; path = RunnerTests.xctest; sourceTree = BUILT_PRODUCTS_DIR; }; + 3B3967151E833CAA004F5970 /* AppFrameworkInfo.plist */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.plist.xml; name = AppFrameworkInfo.plist; path = Flutter/AppFrameworkInfo.plist; sourceTree = ""; }; + 74858FAD1ED2DC5600515810 /* Runner-Bridging-Header.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = "Runner-Bridging-Header.h"; sourceTree = ""; }; + 74858FAE1ED2DC5600515810 /* AppDelegate.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = AppDelegate.swift; sourceTree = ""; }; + 7884E8672EC3CC0400C636F2 /* SceneDelegate.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SceneDelegate.swift; sourceTree = ""; }; + 7AFA3C8E1D35360C0083082E /* Release.xcconfig */ = {isa = PBXFileReference; lastKnownFileType = text.xcconfig; name = Release.xcconfig; path = Flutter/Release.xcconfig; sourceTree = ""; }; + 9740EEB21CF90195004384FC /* Debug.xcconfig */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.xcconfig; name = Debug.xcconfig; path = Flutter/Debug.xcconfig; sourceTree = ""; }; + 9740EEB31CF90195004384FC /* Generated.xcconfig */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.xcconfig; name = Generated.xcconfig; path = Flutter/Generated.xcconfig; sourceTree = ""; }; + 97C146EE1CF9000F007C117D /* Runner.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = Runner.app; sourceTree = BUILT_PRODUCTS_DIR; }; + 97C146FB1CF9000F007C117D /* Base */ = {isa = PBXFileReference; lastKnownFileType = file.storyboard; name = Base; path = Base.lproj/Main.storyboard; sourceTree = ""; }; + 97C146FD1CF9000F007C117D /* Assets.xcassets */ = {isa = PBXFileReference; lastKnownFileType = folder.assetcatalog; path = Assets.xcassets; sourceTree = ""; }; + 97C147001CF9000F007C117D /* Base */ = {isa = PBXFileReference; lastKnownFileType = file.storyboard; name = Base; path = Base.lproj/LaunchScreen.storyboard; sourceTree = ""; }; + 97C147021CF9000F007C117D /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = ""; }; +/* End PBXFileReference section */ + +/* Begin PBXFrameworksBuildPhase section */ + 97C146EB1CF9000F007C117D /* Frameworks */ = { + isa = PBXFrameworksBuildPhase; + buildActionMask = 2147483647; + files = ( + ); + runOnlyForDeploymentPostprocessing = 0; + }; +/* End PBXFrameworksBuildPhase section */ + +/* Begin PBXGroup section */ + 331C8082294A63A400263BE5 /* RunnerTests */ = { + isa = PBXGroup; + children = ( + 331C807B294A618700263BE5 /* RunnerTests.swift */, + ); + path = RunnerTests; + sourceTree = ""; + }; + 9740EEB11CF90186004384FC /* Flutter */ = { + isa = PBXGroup; + children = ( + 3B3967151E833CAA004F5970 /* AppFrameworkInfo.plist */, + 9740EEB21CF90195004384FC /* Debug.xcconfig */, + 7AFA3C8E1D35360C0083082E /* Release.xcconfig */, + 9740EEB31CF90195004384FC /* Generated.xcconfig */, + ); + name = Flutter; + sourceTree = ""; + }; + 97C146E51CF9000F007C117D = { + isa = PBXGroup; + children = ( + 9740EEB11CF90186004384FC /* Flutter */, + 97C146F01CF9000F007C117D /* Runner */, + 97C146EF1CF9000F007C117D /* Products */, + 331C8082294A63A400263BE5 /* RunnerTests */, + ); + sourceTree = ""; + }; + 97C146EF1CF9000F007C117D /* Products */ = { + isa = PBXGroup; + children = ( + 97C146EE1CF9000F007C117D /* Runner.app */, + 331C8081294A63A400263BE5 /* RunnerTests.xctest */, + ); + name = Products; + sourceTree = ""; + }; + 97C146F01CF9000F007C117D /* Runner */ = { + isa = PBXGroup; + children = ( + 97C146FA1CF9000F007C117D /* Main.storyboard */, + 97C146FD1CF9000F007C117D /* Assets.xcassets */, + 97C146FF1CF9000F007C117D /* LaunchScreen.storyboard */, + 97C147021CF9000F007C117D /* Info.plist */, + 1498D2321E8E86230040F4C2 /* GeneratedPluginRegistrant.h */, + 1498D2331E8E89220040F4C2 /* GeneratedPluginRegistrant.m */, + 74858FAE1ED2DC5600515810 /* AppDelegate.swift */, + 7884E8672EC3CC0400C636F2 /* SceneDelegate.swift */, + 74858FAD1ED2DC5600515810 /* Runner-Bridging-Header.h */, + ); + path = Runner; + sourceTree = ""; + }; +/* End PBXGroup section */ + +/* Begin PBXNativeTarget section */ + 331C8080294A63A400263BE5 /* RunnerTests */ = { + isa = PBXNativeTarget; + buildConfigurationList = 331C8087294A63A400263BE5 /* Build configuration list for PBXNativeTarget "RunnerTests" */; + buildPhases = ( + 331C807D294A63A400263BE5 /* Sources */, + 331C807F294A63A400263BE5 /* Resources */, + ); + buildRules = ( + ); + dependencies = ( + 331C8086294A63A400263BE5 /* PBXTargetDependency */, + ); + name = RunnerTests; + productName = RunnerTests; + productReference = 331C8081294A63A400263BE5 /* RunnerTests.xctest */; + productType = "com.apple.product-type.bundle.unit-test"; + }; + 97C146ED1CF9000F007C117D /* Runner */ = { + isa = PBXNativeTarget; + buildConfigurationList = 97C147051CF9000F007C117D /* Build configuration list for PBXNativeTarget "Runner" */; + buildPhases = ( + 9740EEB61CF901F6004384FC /* Run Script */, + 97C146EA1CF9000F007C117D /* Sources */, + 97C146EB1CF9000F007C117D /* Frameworks */, + 97C146EC1CF9000F007C117D /* Resources */, + 9705A1C41CF9048500538489 /* Embed Frameworks */, + 3B06AD1E1E4923F5004D2608 /* Thin Binary */, + ); + buildRules = ( + ); + dependencies = ( + ); + name = Runner; + productName = Runner; + productReference = 97C146EE1CF9000F007C117D /* Runner.app */; + productType = "com.apple.product-type.application"; + }; +/* End PBXNativeTarget section */ + +/* Begin PBXProject section */ + 97C146E61CF9000F007C117D /* Project object */ = { + isa = PBXProject; + attributes = { + BuildIndependentTargetsInParallel = YES; + LastUpgradeCheck = 1510; + ORGANIZATIONNAME = ""; + TargetAttributes = { + 331C8080294A63A400263BE5 = { + CreatedOnToolsVersion = 14.0; + TestTargetID = 97C146ED1CF9000F007C117D; + }; + 97C146ED1CF9000F007C117D = { + CreatedOnToolsVersion = 7.3.1; + LastSwiftMigration = 1100; + }; + }; + }; + buildConfigurationList = 97C146E91CF9000F007C117D /* Build configuration list for PBXProject "Runner" */; + compatibilityVersion = "Xcode 9.3"; + developmentRegion = en; + hasScannedForEncodings = 0; + knownRegions = ( + en, + Base, + ); + mainGroup = 97C146E51CF9000F007C117D; + productRefGroup = 97C146EF1CF9000F007C117D /* Products */; + projectDirPath = ""; + projectRoot = ""; + targets = ( + 97C146ED1CF9000F007C117D /* Runner */, + 331C8080294A63A400263BE5 /* RunnerTests */, + ); + }; +/* End PBXProject section */ + +/* Begin PBXResourcesBuildPhase section */ + 331C807F294A63A400263BE5 /* Resources */ = { + isa = PBXResourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + ); + runOnlyForDeploymentPostprocessing = 0; + }; + 97C146EC1CF9000F007C117D /* Resources */ = { + isa = PBXResourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + 97C147011CF9000F007C117D /* LaunchScreen.storyboard in Resources */, + 3B3967161E833CAA004F5970 /* AppFrameworkInfo.plist in Resources */, + 97C146FE1CF9000F007C117D /* Assets.xcassets in Resources */, + 97C146FC1CF9000F007C117D /* Main.storyboard in Resources */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; +/* End PBXResourcesBuildPhase section */ + +/* Begin PBXShellScriptBuildPhase section */ + 3B06AD1E1E4923F5004D2608 /* Thin Binary */ = { + isa = PBXShellScriptBuildPhase; + alwaysOutOfDate = 1; + buildActionMask = 2147483647; + files = ( + ); + inputPaths = ( + "${TARGET_BUILD_DIR}/${INFOPLIST_PATH}", + ); + name = "Thin Binary"; + outputPaths = ( + ); + runOnlyForDeploymentPostprocessing = 0; + shellPath = /bin/sh; + shellScript = "/bin/sh \"$FLUTTER_ROOT/packages/flutter_tools/bin/xcode_backend.sh\" embed_and_thin"; + }; + 9740EEB61CF901F6004384FC /* Run Script */ = { + isa = PBXShellScriptBuildPhase; + alwaysOutOfDate = 1; + buildActionMask = 2147483647; + files = ( + ); + inputPaths = ( + ); + name = "Run Script"; + outputPaths = ( + ); + runOnlyForDeploymentPostprocessing = 0; + shellPath = /bin/sh; + shellScript = "/bin/sh \"$FLUTTER_ROOT/packages/flutter_tools/bin/xcode_backend.sh\" build"; + }; +/* End PBXShellScriptBuildPhase section */ + +/* Begin PBXSourcesBuildPhase section */ + 331C807D294A63A400263BE5 /* Sources */ = { + isa = PBXSourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + 331C808B294A63AB00263BE5 /* RunnerTests.swift in Sources */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; + 97C146EA1CF9000F007C117D /* Sources */ = { + isa = PBXSourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + 74858FAF1ED2DC5600515810 /* AppDelegate.swift in Sources */, + 1498D2341E8E89220040F4C2 /* GeneratedPluginRegistrant.m in Sources */, + 7884E8682EC3CC0700C636F2 /* SceneDelegate.swift in Sources */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; +/* End PBXSourcesBuildPhase section */ + +/* Begin PBXTargetDependency section */ + 331C8086294A63A400263BE5 /* PBXTargetDependency */ = { + isa = PBXTargetDependency; + target = 97C146ED1CF9000F007C117D /* Runner */; + targetProxy = 331C8085294A63A400263BE5 /* PBXContainerItemProxy */; + }; +/* End PBXTargetDependency section */ + +/* Begin PBXVariantGroup section */ + 97C146FA1CF9000F007C117D /* Main.storyboard */ = { + isa = PBXVariantGroup; + children = ( + 97C146FB1CF9000F007C117D /* Base */, + ); + name = Main.storyboard; + sourceTree = ""; + }; + 97C146FF1CF9000F007C117D /* LaunchScreen.storyboard */ = { + isa = PBXVariantGroup; + children = ( + 97C147001CF9000F007C117D /* Base */, + ); + name = LaunchScreen.storyboard; + sourceTree = ""; + }; +/* End PBXVariantGroup section */ + +/* Begin XCBuildConfiguration section */ + 249021D3217E4FDB00AE95B9 /* Profile */ = { + isa = XCBuildConfiguration; + buildSettings = { + ALWAYS_SEARCH_USER_PATHS = NO; + ASSETCATALOG_COMPILER_GENERATE_SWIFT_ASSET_SYMBOL_EXTENSIONS = YES; + CLANG_ANALYZER_NONNULL = YES; + CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x"; + CLANG_CXX_LIBRARY = "libc++"; + CLANG_ENABLE_MODULES = YES; + CLANG_ENABLE_OBJC_ARC = YES; + CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES; + CLANG_WARN_BOOL_CONVERSION = YES; + CLANG_WARN_COMMA = YES; + CLANG_WARN_CONSTANT_CONVERSION = YES; + CLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES; + CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; + CLANG_WARN_EMPTY_BODY = YES; + CLANG_WARN_ENUM_CONVERSION = YES; + CLANG_WARN_INFINITE_RECURSION = YES; + CLANG_WARN_INT_CONVERSION = YES; + CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES; + CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = YES; + CLANG_WARN_OBJC_LITERAL_CONVERSION = YES; + CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; + CLANG_WARN_RANGE_LOOP_ANALYSIS = YES; + CLANG_WARN_STRICT_PROTOTYPES = YES; + CLANG_WARN_SUSPICIOUS_MOVE = YES; + CLANG_WARN_UNREACHABLE_CODE = YES; + CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; + "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer"; + COPY_PHASE_STRIP = NO; + DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym"; + ENABLE_NS_ASSERTIONS = NO; + ENABLE_STRICT_OBJC_MSGSEND = YES; + ENABLE_USER_SCRIPT_SANDBOXING = NO; + GCC_C_LANGUAGE_STANDARD = gnu99; + GCC_NO_COMMON_BLOCKS = YES; + GCC_WARN_64_TO_32_BIT_CONVERSION = YES; + GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; + GCC_WARN_UNDECLARED_SELECTOR = YES; + GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; + GCC_WARN_UNUSED_FUNCTION = YES; + GCC_WARN_UNUSED_VARIABLE = YES; + IPHONEOS_DEPLOYMENT_TARGET = 13.0; + MTL_ENABLE_DEBUG_INFO = NO; + SDKROOT = iphoneos; + SUPPORTED_PLATFORMS = iphoneos; + TARGETED_DEVICE_FAMILY = "1,2"; + VALIDATE_PRODUCT = YES; + }; + name = Profile; + }; + 249021D4217E4FDB00AE95B9 /* Profile */ = { + isa = XCBuildConfiguration; + baseConfigurationReference = 7AFA3C8E1D35360C0083082E /* Release.xcconfig */; + buildSettings = { + ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; + CLANG_ENABLE_MODULES = YES; + CURRENT_PROJECT_VERSION = "$(FLUTTER_BUILD_NUMBER)"; + DEVELOPMENT_TEAM = 767CSPQD7Q; + ENABLE_BITCODE = NO; + INFOPLIST_FILE = Runner/Info.plist; + LD_RUNPATH_SEARCH_PATHS = ( + "$(inherited)", + "@executable_path/Frameworks", + ); + PRODUCT_BUNDLE_IDENTIFIER = in.inmodel.premithus; + PRODUCT_NAME = "$(TARGET_NAME)"; + SWIFT_OBJC_BRIDGING_HEADER = "Runner/Runner-Bridging-Header.h"; + SWIFT_VERSION = 5.0; + VERSIONING_SYSTEM = "apple-generic"; + }; + name = Profile; + }; + 331C8088294A63A400263BE5 /* Debug */ = { + isa = XCBuildConfiguration; + buildSettings = { + BUNDLE_LOADER = "$(TEST_HOST)"; + CODE_SIGN_STYLE = Automatic; + CURRENT_PROJECT_VERSION = 1; + GENERATE_INFOPLIST_FILE = YES; + MARKETING_VERSION = 1.0; + PRODUCT_BUNDLE_IDENTIFIER = in.inmodel.premithus.RunnerTests; + PRODUCT_NAME = "$(TARGET_NAME)"; + SWIFT_ACTIVE_COMPILATION_CONDITIONS = DEBUG; + SWIFT_OPTIMIZATION_LEVEL = "-Onone"; + SWIFT_VERSION = 5.0; + TEST_HOST = "$(BUILT_PRODUCTS_DIR)/Runner.app/$(BUNDLE_EXECUTABLE_FOLDER_PATH)/Runner"; + }; + name = Debug; + }; + 331C8089294A63A400263BE5 /* Release */ = { + isa = XCBuildConfiguration; + buildSettings = { + BUNDLE_LOADER = "$(TEST_HOST)"; + CODE_SIGN_STYLE = Automatic; + CURRENT_PROJECT_VERSION = 1; + GENERATE_INFOPLIST_FILE = YES; + MARKETING_VERSION = 1.0; + PRODUCT_BUNDLE_IDENTIFIER = in.inmodel.premithus.RunnerTests; + PRODUCT_NAME = "$(TARGET_NAME)"; + SWIFT_VERSION = 5.0; + TEST_HOST = "$(BUILT_PRODUCTS_DIR)/Runner.app/$(BUNDLE_EXECUTABLE_FOLDER_PATH)/Runner"; + }; + name = Release; + }; + 331C808A294A63A400263BE5 /* Profile */ = { + isa = XCBuildConfiguration; + buildSettings = { + BUNDLE_LOADER = "$(TEST_HOST)"; + CODE_SIGN_STYLE = Automatic; + CURRENT_PROJECT_VERSION = 1; + GENERATE_INFOPLIST_FILE = YES; + MARKETING_VERSION = 1.0; + PRODUCT_BUNDLE_IDENTIFIER = in.inmodel.premithus.RunnerTests; + PRODUCT_NAME = "$(TARGET_NAME)"; + SWIFT_VERSION = 5.0; + TEST_HOST = "$(BUILT_PRODUCTS_DIR)/Runner.app/$(BUNDLE_EXECUTABLE_FOLDER_PATH)/Runner"; + }; + name = Profile; + }; + 97C147031CF9000F007C117D /* Debug */ = { + isa = XCBuildConfiguration; + buildSettings = { + ALWAYS_SEARCH_USER_PATHS = NO; + ASSETCATALOG_COMPILER_GENERATE_SWIFT_ASSET_SYMBOL_EXTENSIONS = YES; + CLANG_ANALYZER_NONNULL = YES; + CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x"; + CLANG_CXX_LIBRARY = "libc++"; + CLANG_ENABLE_MODULES = YES; + CLANG_ENABLE_OBJC_ARC = YES; + CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES; + CLANG_WARN_BOOL_CONVERSION = YES; + CLANG_WARN_COMMA = YES; + CLANG_WARN_CONSTANT_CONVERSION = YES; + CLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES; + CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; + CLANG_WARN_EMPTY_BODY = YES; + CLANG_WARN_ENUM_CONVERSION = YES; + CLANG_WARN_INFINITE_RECURSION = YES; + CLANG_WARN_INT_CONVERSION = YES; + CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES; + CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = YES; + CLANG_WARN_OBJC_LITERAL_CONVERSION = YES; + CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; + CLANG_WARN_RANGE_LOOP_ANALYSIS = YES; + CLANG_WARN_STRICT_PROTOTYPES = YES; + CLANG_WARN_SUSPICIOUS_MOVE = YES; + CLANG_WARN_UNREACHABLE_CODE = YES; + CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; + "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer"; + COPY_PHASE_STRIP = NO; + DEBUG_INFORMATION_FORMAT = dwarf; + ENABLE_STRICT_OBJC_MSGSEND = YES; + ENABLE_TESTABILITY = YES; + ENABLE_USER_SCRIPT_SANDBOXING = NO; + GCC_C_LANGUAGE_STANDARD = gnu99; + GCC_DYNAMIC_NO_PIC = NO; + GCC_NO_COMMON_BLOCKS = YES; + GCC_OPTIMIZATION_LEVEL = 0; + GCC_PREPROCESSOR_DEFINITIONS = ( + "DEBUG=1", + "$(inherited)", + ); + GCC_WARN_64_TO_32_BIT_CONVERSION = YES; + GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; + GCC_WARN_UNDECLARED_SELECTOR = YES; + GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; + GCC_WARN_UNUSED_FUNCTION = YES; + GCC_WARN_UNUSED_VARIABLE = YES; + IPHONEOS_DEPLOYMENT_TARGET = 13.0; + MTL_ENABLE_DEBUG_INFO = YES; + ONLY_ACTIVE_ARCH = YES; + SDKROOT = iphoneos; + TARGETED_DEVICE_FAMILY = "1,2"; + }; + name = Debug; + }; + 97C147041CF9000F007C117D /* Release */ = { + isa = XCBuildConfiguration; + buildSettings = { + ALWAYS_SEARCH_USER_PATHS = NO; + ASSETCATALOG_COMPILER_GENERATE_SWIFT_ASSET_SYMBOL_EXTENSIONS = YES; + CLANG_ANALYZER_NONNULL = YES; + CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x"; + CLANG_CXX_LIBRARY = "libc++"; + CLANG_ENABLE_MODULES = YES; + CLANG_ENABLE_OBJC_ARC = YES; + CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES; + CLANG_WARN_BOOL_CONVERSION = YES; + CLANG_WARN_COMMA = YES; + CLANG_WARN_CONSTANT_CONVERSION = YES; + CLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES; + CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; + CLANG_WARN_EMPTY_BODY = YES; + CLANG_WARN_ENUM_CONVERSION = YES; + CLANG_WARN_INFINITE_RECURSION = YES; + CLANG_WARN_INT_CONVERSION = YES; + CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES; + CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = YES; + CLANG_WARN_OBJC_LITERAL_CONVERSION = YES; + CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; + CLANG_WARN_RANGE_LOOP_ANALYSIS = YES; + CLANG_WARN_STRICT_PROTOTYPES = YES; + CLANG_WARN_SUSPICIOUS_MOVE = YES; + CLANG_WARN_UNREACHABLE_CODE = YES; + CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; + "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer"; + COPY_PHASE_STRIP = NO; + DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym"; + ENABLE_NS_ASSERTIONS = NO; + ENABLE_STRICT_OBJC_MSGSEND = YES; + ENABLE_USER_SCRIPT_SANDBOXING = NO; + GCC_C_LANGUAGE_STANDARD = gnu99; + GCC_NO_COMMON_BLOCKS = YES; + GCC_WARN_64_TO_32_BIT_CONVERSION = YES; + GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; + GCC_WARN_UNDECLARED_SELECTOR = YES; + GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; + GCC_WARN_UNUSED_FUNCTION = YES; + GCC_WARN_UNUSED_VARIABLE = YES; + IPHONEOS_DEPLOYMENT_TARGET = 13.0; + MTL_ENABLE_DEBUG_INFO = NO; + SDKROOT = iphoneos; + SUPPORTED_PLATFORMS = iphoneos; + SWIFT_COMPILATION_MODE = wholemodule; + SWIFT_OPTIMIZATION_LEVEL = "-O"; + TARGETED_DEVICE_FAMILY = "1,2"; + VALIDATE_PRODUCT = YES; + }; + name = Release; + }; + 97C147061CF9000F007C117D /* Debug */ = { + isa = XCBuildConfiguration; + baseConfigurationReference = 9740EEB21CF90195004384FC /* Debug.xcconfig */; + buildSettings = { + ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; + CLANG_ENABLE_MODULES = YES; + CURRENT_PROJECT_VERSION = "$(FLUTTER_BUILD_NUMBER)"; + DEVELOPMENT_TEAM = 767CSPQD7Q; + ENABLE_BITCODE = NO; + INFOPLIST_FILE = Runner/Info.plist; + LD_RUNPATH_SEARCH_PATHS = ( + "$(inherited)", + "@executable_path/Frameworks", + ); + PRODUCT_BUNDLE_IDENTIFIER = in.inmodel.premithus; + PRODUCT_NAME = "$(TARGET_NAME)"; + SWIFT_OBJC_BRIDGING_HEADER = "Runner/Runner-Bridging-Header.h"; + SWIFT_OPTIMIZATION_LEVEL = "-Onone"; + SWIFT_VERSION = 5.0; + VERSIONING_SYSTEM = "apple-generic"; + }; + name = Debug; + }; + 97C147071CF9000F007C117D /* Release */ = { + isa = XCBuildConfiguration; + baseConfigurationReference = 7AFA3C8E1D35360C0083082E /* Release.xcconfig */; + buildSettings = { + ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; + CLANG_ENABLE_MODULES = YES; + CURRENT_PROJECT_VERSION = "$(FLUTTER_BUILD_NUMBER)"; + DEVELOPMENT_TEAM = 767CSPQD7Q; + ENABLE_BITCODE = NO; + INFOPLIST_FILE = Runner/Info.plist; + LD_RUNPATH_SEARCH_PATHS = ( + "$(inherited)", + "@executable_path/Frameworks", + ); + PRODUCT_BUNDLE_IDENTIFIER = in.inmodel.premithus; + PRODUCT_NAME = "$(TARGET_NAME)"; + SWIFT_OBJC_BRIDGING_HEADER = "Runner/Runner-Bridging-Header.h"; + SWIFT_VERSION = 5.0; + VERSIONING_SYSTEM = "apple-generic"; + }; + name = Release; + }; +/* End XCBuildConfiguration section */ + +/* Begin XCConfigurationList section */ + 331C8087294A63A400263BE5 /* Build configuration list for PBXNativeTarget "RunnerTests" */ = { + isa = XCConfigurationList; + buildConfigurations = ( + 331C8088294A63A400263BE5 /* Debug */, + 331C8089294A63A400263BE5 /* Release */, + 331C808A294A63A400263BE5 /* Profile */, + ); + defaultConfigurationIsVisible = 0; + defaultConfigurationName = Release; + }; + 97C146E91CF9000F007C117D /* Build configuration list for PBXProject "Runner" */ = { + isa = XCConfigurationList; + buildConfigurations = ( + 97C147031CF9000F007C117D /* Debug */, + 97C147041CF9000F007C117D /* Release */, + 249021D3217E4FDB00AE95B9 /* Profile */, + ); + defaultConfigurationIsVisible = 0; + defaultConfigurationName = Release; + }; + 97C147051CF9000F007C117D /* Build configuration list for PBXNativeTarget "Runner" */ = { + isa = XCConfigurationList; + buildConfigurations = ( + 97C147061CF9000F007C117D /* Debug */, + 97C147071CF9000F007C117D /* Release */, + 249021D4217E4FDB00AE95B9 /* Profile */, + ); + defaultConfigurationIsVisible = 0; + defaultConfigurationName = Release; + }; +/* End XCConfigurationList section */ + }; + rootObject = 97C146E61CF9000F007C117D /* Project object */; +} diff --git a/ios/Runner.xcodeproj/project.xcworkspace/contents.xcworkspacedata b/ios/Runner.xcodeproj/project.xcworkspace/contents.xcworkspacedata new file mode 100644 index 0000000000000000000000000000000000000000..919434a6254f0e9651f402737811be6634a03e9c --- /dev/null +++ b/ios/Runner.xcodeproj/project.xcworkspace/contents.xcworkspacedata @@ -0,0 +1,7 @@ + + + + + diff --git a/ios/Runner.xcodeproj/project.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist b/ios/Runner.xcodeproj/project.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist new file mode 100644 index 0000000000000000000000000000000000000000..18d981003d68d0546c4804ac2ff47dd97c6e7921 --- /dev/null +++ b/ios/Runner.xcodeproj/project.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist @@ -0,0 +1,8 @@ + + + + + IDEDidComputeMac32BitWarning + + + diff --git a/ios/Runner.xcodeproj/project.xcworkspace/xcshareddata/WorkspaceSettings.xcsettings b/ios/Runner.xcodeproj/project.xcworkspace/xcshareddata/WorkspaceSettings.xcsettings new file mode 100644 index 0000000000000000000000000000000000000000..f9b0d7c5ea15f194be85eb6ee8e6721a87ff4644 --- /dev/null +++ b/ios/Runner.xcodeproj/project.xcworkspace/xcshareddata/WorkspaceSettings.xcsettings @@ -0,0 +1,8 @@ + + + + + PreviewsEnabled + + + diff --git a/ios/Runner.xcodeproj/xcshareddata/xcschemes/Runner.xcscheme b/ios/Runner.xcodeproj/xcshareddata/xcschemes/Runner.xcscheme new file mode 100644 index 0000000000000000000000000000000000000000..e3773d42e24c8bb3b9070fc9d10d62032787035e --- /dev/null +++ b/ios/Runner.xcodeproj/xcshareddata/xcschemes/Runner.xcscheme @@ -0,0 +1,101 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/ios/Runner.xcworkspace/contents.xcworkspacedata b/ios/Runner.xcworkspace/contents.xcworkspacedata new file mode 100644 index 0000000000000000000000000000000000000000..1d526a16ed0f1cd0c2409d848bf489b93fefa3b2 --- /dev/null +++ b/ios/Runner.xcworkspace/contents.xcworkspacedata @@ -0,0 +1,7 @@ + + + + + diff --git a/ios/Runner.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist b/ios/Runner.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist new file mode 100644 index 0000000000000000000000000000000000000000..18d981003d68d0546c4804ac2ff47dd97c6e7921 --- /dev/null +++ b/ios/Runner.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist @@ -0,0 +1,8 @@ + + + + + IDEDidComputeMac32BitWarning + + + diff --git a/ios/Runner.xcworkspace/xcshareddata/WorkspaceSettings.xcsettings b/ios/Runner.xcworkspace/xcshareddata/WorkspaceSettings.xcsettings new file mode 100644 index 0000000000000000000000000000000000000000..f9b0d7c5ea15f194be85eb6ee8e6721a87ff4644 --- /dev/null +++ b/ios/Runner.xcworkspace/xcshareddata/WorkspaceSettings.xcsettings @@ -0,0 +1,8 @@ + + + + + PreviewsEnabled + + + diff --git a/ios/Runner/AppDelegate.swift b/ios/Runner/AppDelegate.swift new file mode 100644 index 0000000000000000000000000000000000000000..c30b367ec0a99a3f38e09477c49ba6b5adeb352d --- /dev/null +++ b/ios/Runner/AppDelegate.swift @@ -0,0 +1,16 @@ +import Flutter +import UIKit + +@main +@objc class AppDelegate: FlutterAppDelegate, FlutterImplicitEngineDelegate { + override func application( + _ application: UIApplication, + didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]? + ) -> Bool { + return super.application(application, didFinishLaunchingWithOptions: launchOptions) + } + + func didInitializeImplicitFlutterEngine(_ engineBridge: FlutterImplicitEngineBridge) { + GeneratedPluginRegistrant.register(with: engineBridge.pluginRegistry) + } +} diff --git a/ios/Runner/Assets.xcassets/AppIcon.appiconset/Contents.json b/ios/Runner/Assets.xcassets/AppIcon.appiconset/Contents.json new file mode 100644 index 0000000000000000000000000000000000000000..d36b1fab2d9dea668a4f83df94d525897d9e68dd --- /dev/null +++ b/ios/Runner/Assets.xcassets/AppIcon.appiconset/Contents.json @@ -0,0 +1,122 @@ +{ + "images" : [ + { + "size" : "20x20", + "idiom" : "iphone", + "filename" : "Icon-App-20x20@2x.png", + "scale" : "2x" + }, + { + "size" : "20x20", + "idiom" : "iphone", + "filename" : "Icon-App-20x20@3x.png", + "scale" : "3x" + }, + { + "size" : "29x29", + "idiom" : "iphone", + "filename" : "Icon-App-29x29@1x.png", + "scale" : "1x" + }, + { + "size" : "29x29", + "idiom" : "iphone", + "filename" : "Icon-App-29x29@2x.png", + "scale" : "2x" + }, + { + "size" : "29x29", + "idiom" : "iphone", + "filename" : "Icon-App-29x29@3x.png", + "scale" : "3x" + }, + { + "size" : "40x40", + "idiom" : "iphone", + "filename" : "Icon-App-40x40@2x.png", + "scale" : "2x" + }, + { + "size" : "40x40", + "idiom" : "iphone", + "filename" : "Icon-App-40x40@3x.png", + "scale" : "3x" + }, + { + "size" : "60x60", + "idiom" : "iphone", + "filename" : "Icon-App-60x60@2x.png", + "scale" : "2x" + }, + { + "size" : "60x60", + "idiom" : "iphone", + "filename" : "Icon-App-60x60@3x.png", + "scale" : "3x" + }, + { + "size" : "20x20", + "idiom" : "ipad", + "filename" : "Icon-App-20x20@1x.png", + "scale" : "1x" + }, + { + "size" : "20x20", + "idiom" : "ipad", + "filename" : "Icon-App-20x20@2x.png", + "scale" : "2x" + }, + { + "size" : "29x29", + "idiom" : "ipad", + "filename" : "Icon-App-29x29@1x.png", + "scale" : "1x" + }, + { + "size" : "29x29", + "idiom" : "ipad", + "filename" : "Icon-App-29x29@2x.png", + "scale" : "2x" + }, + { + "size" : "40x40", + "idiom" : "ipad", + "filename" : "Icon-App-40x40@1x.png", + "scale" : "1x" + }, + { + "size" : "40x40", + "idiom" : "ipad", + "filename" : "Icon-App-40x40@2x.png", + "scale" : "2x" + }, + { + "size" : "76x76", + "idiom" : "ipad", + "filename" : "Icon-App-76x76@1x.png", + "scale" : "1x" + }, + { + "size" : "76x76", + "idiom" : "ipad", + "filename" : "Icon-App-76x76@2x.png", + "scale" : "2x" + }, + { + "size" : "83.5x83.5", + "idiom" : "ipad", + "filename" : "Icon-App-83.5x83.5@2x.png", + "scale" : "2x" + }, + { + "size" : "1024x1024", + "idiom" : "ios-marketing", + "filename" : "Icon-App-1024x1024@1x.png", + "scale" : "1x" + } + ], + "info" : { + "version" : 1, + "author" : "xcode" + } +} diff --git a/ios/Runner/Assets.xcassets/LaunchImage.imageset/Contents.json b/ios/Runner/Assets.xcassets/LaunchImage.imageset/Contents.json new file mode 100644 index 0000000000000000000000000000000000000000..0bedcf2fd46788ae3a01a423467513ff59b5c120 --- /dev/null +++ b/ios/Runner/Assets.xcassets/LaunchImage.imageset/Contents.json @@ -0,0 +1,23 @@ +{ + "images" : [ + { + "idiom" : "universal", + "filename" : "LaunchImage.png", + "scale" : "1x" + }, + { + "idiom" : "universal", + "filename" : "LaunchImage@2x.png", + "scale" : "2x" + }, + { + "idiom" : "universal", + "filename" : "LaunchImage@3x.png", + "scale" : "3x" + } + ], + "info" : { + "version" : 1, + "author" : "xcode" + } +} diff --git a/ios/Runner/Assets.xcassets/LaunchImage.imageset/README.md b/ios/Runner/Assets.xcassets/LaunchImage.imageset/README.md new file mode 100644 index 0000000000000000000000000000000000000000..89c2725b70f1882be97f5214fafe22d27a0ec01e --- /dev/null +++ b/ios/Runner/Assets.xcassets/LaunchImage.imageset/README.md @@ -0,0 +1,5 @@ +# Launch Screen Assets + +You can customize the launch screen with your own desired assets by replacing the image files in this directory. + +You can also do it by opening your Flutter project's Xcode project with `open ios/Runner.xcworkspace`, selecting `Runner/Assets.xcassets` in the Project Navigator and dropping in the desired images. \ No newline at end of file diff --git a/ios/Runner/Base.lproj/LaunchScreen.storyboard b/ios/Runner/Base.lproj/LaunchScreen.storyboard new file mode 100644 index 0000000000000000000000000000000000000000..f2e259c7c9390ff69a6bbe1e0907e6dc366848e7 --- /dev/null +++ b/ios/Runner/Base.lproj/LaunchScreen.storyboard @@ -0,0 +1,37 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/ios/Runner/Base.lproj/Main.storyboard b/ios/Runner/Base.lproj/Main.storyboard new file mode 100644 index 0000000000000000000000000000000000000000..f3c28516fb38e64d88cfcf5fb1791175df078f2f --- /dev/null +++ b/ios/Runner/Base.lproj/Main.storyboard @@ -0,0 +1,26 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/ios/Runner/Info.plist b/ios/Runner/Info.plist new file mode 100644 index 0000000000000000000000000000000000000000..adfb8a1d7a051c2e9e58ba2427af85d8fdfc9a5a --- /dev/null +++ b/ios/Runner/Info.plist @@ -0,0 +1,70 @@ + + + + + CADisableMinimumFrameDurationOnPhone + + CFBundleDevelopmentRegion + $(DEVELOPMENT_LANGUAGE) + CFBundleDisplayName + Premithus + CFBundleExecutable + $(EXECUTABLE_NAME) + CFBundleIdentifier + $(PRODUCT_BUNDLE_IDENTIFIER) + CFBundleInfoDictionaryVersion + 6.0 + CFBundleName + premithus + CFBundlePackageType + APPL + CFBundleShortVersionString + $(FLUTTER_BUILD_NAME) + CFBundleSignature + ???? + CFBundleVersion + $(FLUTTER_BUILD_NUMBER) + LSRequiresIPhoneOS + + UIApplicationSceneManifest + + UIApplicationSupportsMultipleScenes + + UISceneConfigurations + + UIWindowSceneSessionRoleApplication + + + UISceneClassName + UIWindowScene + UISceneConfigurationName + flutter + UISceneDelegateClassName + $(PRODUCT_MODULE_NAME).SceneDelegate + UISceneStoryboardFile + Main + + + + + UIApplicationSupportsIndirectInputEvents + + UILaunchStoryboardName + LaunchScreen + UIMainStoryboardFile + Main + UISupportedInterfaceOrientations + + UIInterfaceOrientationPortrait + UIInterfaceOrientationLandscapeLeft + UIInterfaceOrientationLandscapeRight + + UISupportedInterfaceOrientations~ipad + + UIInterfaceOrientationPortrait + UIInterfaceOrientationPortraitUpsideDown + UIInterfaceOrientationLandscapeLeft + UIInterfaceOrientationLandscapeRight + + + diff --git a/ios/Runner/Runner-Bridging-Header.h b/ios/Runner/Runner-Bridging-Header.h new file mode 100644 index 0000000000000000000000000000000000000000..308a2a560b42f17aaf3c36e4e9c8cd07182fbb7e --- /dev/null +++ b/ios/Runner/Runner-Bridging-Header.h @@ -0,0 +1 @@ +#import "GeneratedPluginRegistrant.h" diff --git a/ios/Runner/SceneDelegate.swift b/ios/Runner/SceneDelegate.swift new file mode 100644 index 0000000000000000000000000000000000000000..b9ce8ea2b2adb8d8061af09c75d2480999773ac3 --- /dev/null +++ b/ios/Runner/SceneDelegate.swift @@ -0,0 +1,6 @@ +import Flutter +import UIKit + +class SceneDelegate: FlutterSceneDelegate { + +} diff --git a/ios/RunnerTests/RunnerTests.swift b/ios/RunnerTests/RunnerTests.swift new file mode 100644 index 0000000000000000000000000000000000000000..86a7c3b1b6119f7dbdb8cec74f1b5b3e076bf949 --- /dev/null +++ b/ios/RunnerTests/RunnerTests.swift @@ -0,0 +1,12 @@ +import Flutter +import UIKit +import XCTest + +class RunnerTests: XCTestCase { + + func testExample() { + // If you add code to the Runner application, consider adding tests here. + // See https://developer.apple.com/documentation/xctest for more information about using XCTest. + } + +} diff --git a/lib/kavacha/kavacha_pipeline.dart b/lib/kavacha/kavacha_pipeline.dart new file mode 100644 index 0000000000000000000000000000000000000000..26e6819d7e3bb1cce1abcc14b3bff7c8b5b67a8f --- /dev/null +++ b/lib/kavacha/kavacha_pipeline.dart @@ -0,0 +1,72 @@ +import '../services/vector_service.dart'; +import '../services/storage_service.dart'; +import 'models/kavacha_models.dart'; +import 'layers/layer0_whitelist.dart'; +import 'layers/layer1_firewall.dart'; +import 'layers/layer2_vector.dart'; +import 'layers/layer3_random_forest.dart'; +import 'layers/layer4_mobile_bert.dart'; +import 'layers/layer5_payload_analyzer.dart'; +class KavachaPipeline { + static final KavachaPipeline _instance = KavachaPipeline._internal(); + factory KavachaPipeline() => _instance; + KavachaPipeline._internal(); + + late List layers; + final Layer4MobileBert _mobileBertLayer = Layer4MobileBert(); + bool _isInit = false; + + Future init() async { + if (_isInit) return; + + // Initialize VectorService (Layer 2) with the app database. + // This is safe — if it fails, VectorService.isReady stays false + // and Layer2Vector will skip itself gracefully. + try { + final db = await StorageService().database; + await VectorService.initialize(db); + + // Seed embeddings on first launch. + if (VectorService.isReady) { + await VectorService().seedEmbeddings(db, 'assets/seed_embeddings.json'); + } + } catch (e) { + print('[KavachaPipeline] VectorService init error (non-fatal): $e'); + } + + await _mobileBertLayer.init(); + + layers = [ + Layer0Whitelist(), + Layer1Firewall(), + Layer5PayloadAnalyzer(), + Layer2Vector(), + Layer3RandomForest(), + _mobileBertLayer, + ]; + + _isInit = true; + final vecStatus = VectorService.isReady ? 'ACTIVE' : 'DISABLED'; + print('[KavachaPipeline] Initialized — Layer 2 (Vector): $vecStatus'); + } + + Future analyze(String sender, String body) async { + final ctx = SmsContext(sender: sender, body: body); + + for (var layer in layers) { + final result = await layer.inspect(ctx); + + if (result.verdict == Verdict.block) { + return result; + } + + if (result.verdict == Verdict.pass) { + return result; + } + // if continueInspection → loop to next layer + } + + // Default fallback if all layers somehow return continueInspection. + return LayerResult.pass(); + } +} diff --git a/lib/kavacha/layers/layer0_whitelist.dart b/lib/kavacha/layers/layer0_whitelist.dart new file mode 100644 index 0000000000000000000000000000000000000000..eedd051a677b424adfa259e97b22e5383f6e18c1 --- /dev/null +++ b/lib/kavacha/layers/layer0_whitelist.dart @@ -0,0 +1,23 @@ +import 'package:sqflite/sqflite.dart'; +import '../../services/storage_service.dart'; +import '../models/kavacha_models.dart'; + +class Layer0Whitelist implements KavachaLayer { + final StorageService _storage = StorageService(); + + @override + Future inspect(SmsContext ctx) async { + final db = await _storage.database; + final results = await db.query( + 'whitelist', + where: 'sender = ?', + whereArgs: [ctx.sender], + ); + + if (results.isNotEmpty) { + return LayerResult.pass(); // Instant pass + } + + return LayerResult.continueInspection(); + } +} diff --git a/lib/kavacha/layers/layer1_firewall.dart b/lib/kavacha/layers/layer1_firewall.dart new file mode 100644 index 0000000000000000000000000000000000000000..b9a8c19b864d37ef5de2a970c8107ac75830b89b --- /dev/null +++ b/lib/kavacha/layers/layer1_firewall.dart @@ -0,0 +1,43 @@ +import '../models/kavacha_models.dart'; + +class Layer1Firewall implements KavachaLayer { + @override + Future inspect(SmsContext ctx) async { + List violations = []; + final lowerBody = ctx.body.toLowerCase(); + + // 1. Sender format + if (ctx.sender.startsWith('+') && ctx.sender.length > 13) { + violations.add("unknown_sender_format"); + } + + // 2. Domain reputation (simple mock matching) + if (lowerBody.contains("http") && !lowerBody.contains("hdfcbank.com") && lowerBody.contains("hdfc")) { + violations.add("domain_reputation_mismatch"); + } + + // 3. Urgency language + if (lowerBody.contains("urgent") || lowerBody.contains("blocked") || lowerBody.contains("suspend")) { + violations.add("urgency_language"); + } + + // 4. Money pattern + if (ctx.body.contains("₹") && (lowerBody.contains("pay") || lowerBody.contains("collect"))) { + violations.add("money_pattern"); + } + + // 5. Temporal anomaly + final hour = DateTime.now().hour; + if (hour < 6 || hour > 22) { + if (lowerBody.contains("kyc") || lowerBody.contains("account")) { + violations.add("temporal_anomaly"); + } + } + + if (violations.length >= 3) { + return LayerResult.block("5-Tuple Firewall Violation", 0.95, violations, 1); + } + + return LayerResult.continueInspection(); + } +} diff --git a/lib/kavacha/layers/layer2_vector.dart b/lib/kavacha/layers/layer2_vector.dart new file mode 100644 index 0000000000000000000000000000000000000000..cbdd5a8d34767678cdfc5da939a4b4ece96cc54f --- /dev/null +++ b/lib/kavacha/layers/layer2_vector.dart @@ -0,0 +1,59 @@ +import '../../services/vector_service.dart'; +import '../../services/storage_service.dart'; +import '../models/kavacha_models.dart'; +import 'dart:math'; + +class Layer2Vector implements KavachaLayer { + @override + Future inspect(SmsContext ctx) async { + // Guard: if VectorService failed to initialize, skip this layer entirely. + if (!VectorService.isReady) { + return LayerResult.continueInspection(); + } + + // Mock-embed the SMS body (128-dim seeded by text hash). + // In production, replace with all-MiniLM TFLite inference. + final embedding = _mockEmbed(ctx.body); + + try { + final db = await StorageService().database; + final match = await VectorService().findClosest( + db: db, + queryEmbedding: embedding, + ); + + if (match != null) { + if (match.isHighRisk) { + // distance < 0.15 → HIGH RISK — skip layers 3 & 4 + return LayerResult.block( + match.category, + 0.90, + ['vector_high_risk', 'distance:${match.distance.toStringAsFixed(3)}'], + 2, + ); + } + if (match.isMediumRisk) { + // distance < 0.35 → MEDIUM RISK — skip layers 3 & 4 + return LayerResult.block( + match.category, + 0.70, + ['vector_medium_risk', 'distance:${match.distance.toStringAsFixed(3)}'], + 2, + ); + } + // distance >= 0.35 → no convincing match → continue to Layer 3 + } + } catch (e) { + print('[Layer2Vector] error: $e'); + } + + return LayerResult.continueInspection(); + } + + /// Deterministic mock embedding: 128 floats seeded by text hashCode. + /// Replace with real TFLite model in production. + List _mockEmbed(String text) { + final rand = Random(text.hashCode); + return List.generate(384, (_) => (rand.nextDouble() * 2) - 1.0); + } +} diff --git a/lib/kavacha/layers/layer3_random_forest.dart b/lib/kavacha/layers/layer3_random_forest.dart new file mode 100644 index 0000000000000000000000000000000000000000..83ffd203cfd934a8390c951489f9d92a4a301cb8 --- /dev/null +++ b/lib/kavacha/layers/layer3_random_forest.dart @@ -0,0 +1,45 @@ +import '../models/kavacha_models.dart'; +import '../models/random_forest_model.dart'; +import '../models/sms_feature_vector.dart'; +import '../threat_pack/festival_calendar.dart'; + +class Layer3RandomForest implements KavachaLayer { + final RandomForestModel _rf = RandomForestModel(); + + @override + Future inspect(SmsContext ctx) async { + final features = _extractFeatures(ctx); + final score = _rf.score(features); + + if (score > 0.80) { + return LayerResult.block("RF Model Detection", score, ["rf_score_>_0.8"], 3); + } else if (score > 0.45 && score <= 0.55) { + // Genuine ambiguity -> Fallback to BERT + return LayerResult.continueInspection(); + } + + // Default pass if score is confidently low (not block, not continue to BERT) + return LayerResult.pass(); + } + + SmsFeatureVector _extractFeatures(SmsContext ctx) { + // Mock feature extraction based on SMS Context + final lower = ctx.body.toLowerCase(); + + return SmsFeatureVector( + senderAgeScore: 0.5, + senderInContacts: false, + senderMessageCount: 1, + senderCarrierScore: 0.8, + urgencyScore: (lower.contains('urgent') || lower.contains('action required')) ? 0.8 : 0.0, + domainCount: lower.contains('http') ? 1 : 0, + domainLevenshtein: lower.contains('http') ? 0.4 : 1.0, + containsMoneyAction: ctx.body.contains('₹') && (lower.contains('pay') || lower.contains('collect')), + capsRatio: 0.1, + hourOfDay: DateTime.now().hour, + isWeekend: DateTime.now().weekday > 5, + isFestivalPeriod: FestivalCalendar().getCurrentSensitivityMultiplier() > 1.0, + recentScamSenderSim: 0.1, + ); + } +} diff --git a/lib/kavacha/layers/layer4_mobile_bert.dart b/lib/kavacha/layers/layer4_mobile_bert.dart new file mode 100644 index 0000000000000000000000000000000000000000..ad8db8a710ef2d2ce8e9ba0ab84113a2ceec8e38 --- /dev/null +++ b/lib/kavacha/layers/layer4_mobile_bert.dart @@ -0,0 +1,85 @@ +import 'dart:math'; +import 'package:tflite_flutter/tflite_flutter.dart'; +import '../models/kavacha_models.dart'; +import '../models/bert_tokenizer.dart'; + +class Layer4MobileBert implements KavachaLayer { + Interpreter? _interpreter; + final BertTokenizer _tokenizer = BertTokenizer(); + bool _isInit = false; + + Future init() async { + if (_isInit) return; + try { + await _tokenizer.init(); + _interpreter = await Interpreter.fromAsset('models/scam_classifier.tflite', + options: InterpreterOptions()..threads = 2); + _isInit = true; + } catch (e) { + print("TFLite not loaded: \$e"); + } + } + + @override + Future inspect(SmsContext ctx) async { + double scamConf = await _runTfliteInference(ctx.body); + + if (!_isInit) { + scamConf = _mockInference(ctx.body); + } + + if (scamConf > 0.80) { + return LayerResult.block("MobileBERT Detection", scamConf, ["bert_confidence"], 4); + } + return LayerResult.pass(); + } + + Future _runTfliteInference(String text) async { + if (!_isInit || _interpreter == null) return 0.0; + + final encoded = _tokenizer.encode(text, maxLen: 128); + var inputIds = [encoded[0]]; + var attentionMask = [encoded[1]]; + + var output = List.filled(2, 0).reshape([1, 2]); + + try { + int inputIdsIdx = 0; + if (_interpreter!.getInputTensors().length > 1) { + final input0Name = _interpreter!.getInputTensor(0).name; + if (input0Name.contains("attention_mask")) { + inputIdsIdx = 1; + } + } + + final inputs = []; + if (inputIdsIdx == 0) { + inputs.add(inputIds); + if (_interpreter!.getInputTensors().length > 1) inputs.add(attentionMask); + } else { + inputs.add(attentionMask); + inputs.add(inputIds); + } + + final outputs = {0: output}; + _interpreter!.runForMultipleInputs(inputs, outputs); + + // Apply softmax since TFBertForSequenceClassification returns logits + double logit0 = output[0][0]; + double logit1 = output[0][1]; + double prob1 = exp(logit1) / (exp(logit0) + exp(logit1)); + + return prob1; + } catch (e) { + print("Inference error: \$e"); + return 0.0; + } + } + + double _mockInference(String text) { + String lower = text.toLowerCase(); + if (lower.contains('hdfcbank-kyc.net') || lower.contains('account blocked')) return 0.95; + if (lower.contains('package cannot be delivered')) return 0.88; + return 0.1; + } +} diff --git a/lib/kavacha/layers/layer5_payload_analyzer.dart b/lib/kavacha/layers/layer5_payload_analyzer.dart new file mode 100644 index 0000000000000000000000000000000000000000..68dff0e3b9ee09eb13eb752aad9ced5a72dba896 --- /dev/null +++ b/lib/kavacha/layers/layer5_payload_analyzer.dart @@ -0,0 +1,110 @@ +import 'dart:io'; +import 'dart:math'; +import '../models/kavacha_models.dart'; + +class Layer5PayloadAnalyzer implements KavachaLayer { + static const List officialDomains = [ + 'sbi.co.in', + 'onlinesbi.sbi', + 'hdfcbank.com', + 'icicibank.com', + 'axisbank.com', + 'incometax.gov.in', + 'indiapost.gov.in', + 'pnbindia.in', + 'epfindia.gov.in', + 'irctc.co.in' + ]; + + @override + Future inspect(SmsContext ctx) async { + final urls = _extractUrls(ctx.body); + if (urls.isEmpty) { + return LayerResult.pass(); + } + + for (String url in urls) { + final domain = _extractDomain(url); + if (domain.isEmpty) continue; + + // 1. Squatter Check + for (String official in officialDomains) { + if (domain == official || domain.endsWith('.\$official')) { + // Exact match, trusted domain + continue; + } + + int distance = _levenshtein(domain, official); + // If it's suspiciously close (distance 1 or 2) but NOT an exact match + if (distance > 0 && distance <= 2) { + return LayerResult.block( + "Domain Squatting Detected", 0.98, ["payload_squatter:\$domain(sim:\$official)"], 5); + } + } + + // 2. Payload Check + bool isApk = await _isApkPayload(url); + if (isApk) { + return LayerResult.block("Malicious APK Payload", 0.99, ["payload_apk:\$url"], 5); + } + } + + return LayerResult.pass(); + } + + List _extractUrls(String text) { + RegExp exp = RegExp( + r"https?:\/\/(www\.)?[-a-zA-Z0-9@:%._\+~#=]{1,256}\.[a-zA-Z0-9()]{1,6}\b([-a-zA-Z0-9()@:%_\+.~#?&//=]*)", + caseSensitive: false); + return exp.allMatches(text).map((m) => m.group(0)!).toList(); + } + + String _extractDomain(String urlString) { + try { + return Uri.parse(urlString).host.toLowerCase(); + } catch (e) { + return ""; + } + } + + Future _isApkPayload(String urlString) async { + if (urlString.toLowerCase().endsWith('.apk')) return true; + + // Attempt lightweight HEAD request for hidden payloads + try { + final client = HttpClient(); + client.connectionTimeout = const Duration(seconds: 3); + final request = await client.headUrl(Uri.parse(urlString)); + request.followRedirects = true; + request.maxRedirects = 3; + final response = await request.close(); + + final contentType = response.headers.value(HttpHeaders.contentTypeHeader); + if (contentType != null && contentType.contains('application/vnd.android.package-archive')) { + return true; + } + } catch (e) { + // Ignore network timeouts silently + } + return false; + } + + int _levenshtein(String a, String b) { + if (a.isEmpty) return b.length; + if (b.isEmpty) return a.length; + + List costs = List.generate(b.length + 1, (i) => i); + for (int i = 0; i < a.length; i++) { + int lastValue = i + 1; + for (int j = 0; j < b.length; j++) { + int newValue = costs[j] + (a[i] == b[j] ? 0 : 1); + if (newValue > lastValue + 1) newValue = lastValue + 1; + if (newValue > costs[j + 1] + 1) newValue = costs[j + 1] + 1; + costs[j] = lastValue; + lastValue = newValue; + } + costs[b.length] = lastValue; + } + return costs[b.length]; + } +} diff --git a/lib/kavacha/models/bert_tokenizer.dart b/lib/kavacha/models/bert_tokenizer.dart new file mode 100644 index 0000000000000000000000000000000000000000..98bacbc54007eb7aad7cb0f5b8f170f334531e8d --- /dev/null +++ b/lib/kavacha/models/bert_tokenizer.dart @@ -0,0 +1,99 @@ +import 'package:flutter/services.dart'; + +class BertTokenizer { + final Map vocab = {}; + bool isReady = false; + + Future init() async { + if (isReady) return; + try { + final vocabString = await rootBundle.loadString('models/vocab.txt'); + final lines = vocabString.split('\n'); + for (int i = 0; i < lines.length; i++) { + final token = lines[i].trim(); + // Since indices are strictly 0-based in the lines list corresponding to the python generation + if (token.isNotEmpty || i == 0) { + vocab[token] = i; + } + } + isReady = true; + } catch (e) { + print("Failed to load vocab.txt: $e"); + } + } + + /// Encodes text to input IDs and returns a tuple of [input_ids, attention_mask] + List> encode(String text, {int maxLen = 128}) { + if (!isReady) { + return [List.filled(maxLen, 0), List.filled(maxLen, 0)]; + } + + text = text.toLowerCase(); + + // Add spaces around punctuation for basic tokenization + text = text.replaceAllMapped(RegExp(r'([^\w\s])'), (match) => ' ${match.group(1)} '); + + final words = text.split(RegExp(r'\s+')).where((e) => e.isNotEmpty).toList(); + final tokens = ['[CLS]']; + + for (var word in words) { + if (word.length > 100) { + tokens.add('[UNK]'); + continue; + } + + int start = 0; + bool isBad = false; + List subTokens = []; + + while (start < word.length) { + int end = word.length; + String curStr = ''; + while (start < end) { + String subStr = word.substring(start, end); + if (start > 0) subStr = '##$subStr'; + if (vocab.containsKey(subStr)) { + curStr = subStr; + break; + } + end--; + } + + if (curStr.isEmpty) { + isBad = true; + break; + } + + subTokens.add(curStr); + start = end; + } + + if (isBad) { + tokens.add('[UNK]'); + } else { + tokens.addAll(subTokens); + } + } + + tokens.add('[SEP]'); + + // Convert to IDs + final ids = tokens.map((t) => vocab[t] ?? vocab['[UNK]'] ?? 100).toList(); + + // Padding / Truncation + List finalIds; + List mask; + if (ids.length > maxLen) { + finalIds = ids.sublist(0, maxLen); + mask = List.filled(maxLen, 1); + } else { + finalIds = List.from(ids); + mask = List.filled(ids.length, 1); + while (finalIds.length < maxLen) { + finalIds.add(0); // [PAD] + mask.add(0); // Mask 0 for padding + } + } + return [finalIds, mask]; + } +} diff --git a/lib/kavacha/models/kavacha_models.dart b/lib/kavacha/models/kavacha_models.dart new file mode 100644 index 0000000000000000000000000000000000000000..30ced2bb4a934f9487a1da8d59ebe8d0d04e1f04 --- /dev/null +++ b/lib/kavacha/models/kavacha_models.dart @@ -0,0 +1,80 @@ +import '../../services/scam_service.dart'; + +enum Verdict { block, pass, continueInspection } + +class LayerResult { + final Verdict verdict; + final String? category; + final double confidence; + final List triggeredDimensions; + final int triggeredLayer; + + LayerResult({ + required this.verdict, + this.category, + this.confidence = 0.0, + this.triggeredDimensions = const [], + this.triggeredLayer = 0, + }); + + factory LayerResult.pass() => LayerResult(verdict: Verdict.pass); + factory LayerResult.continueInspection() => + LayerResult(verdict: Verdict.continueInspection); + factory LayerResult.block( + String category, + double confidence, [ + List? dimensions, + int layer = 0, + ]) => LayerResult( + verdict: Verdict.block, + category: category, + confidence: confidence, + triggeredDimensions: dimensions ?? [], + triggeredLayer: layer, + ); + + /// Human-readable label for the overlay's "Caught by:" line. + String get layerLabel { + switch (triggeredLayer) { + case 1: + return 'India Threat Pack — ${triggeredDimensions.join(", ")}'; + case 2: + return 'Semantic similarity match (Layer 2)'; + case 3: + return 'Pattern classifier (Layer 3)'; + case 4: + return 'Deep language model (Layer 4)'; + default: + return 'Unknown layer'; + } + } + + ScamResult asThreat() => ScamResult( + isScam: true, + confidence: confidence, + category: category ?? 'Unknown', + threatLevel: 'HIGH', + triggeredLayer: triggeredLayer, + layerLabel: layerLabel, + ); + + ScamResult asSafe() => ScamResult( + isScam: false, + confidence: 0.0, + category: 'Safe', + threatLevel: 'SAFE', + triggeredLayer: 0, + layerLabel: '', + ); +} + +class SmsContext { + final String sender; + final String body; + + SmsContext({required this.sender, required this.body}); +} + +abstract class KavachaLayer { + Future inspect(SmsContext ctx); +} diff --git a/lib/kavacha/models/random_forest_model.dart b/lib/kavacha/models/random_forest_model.dart new file mode 100644 index 0000000000000000000000000000000000000000..5bfe980a6a9104e3fbe70fc3b562f137210154e1 --- /dev/null +++ b/lib/kavacha/models/random_forest_model.dart @@ -0,0 +1,194 @@ +// Auto-generated using m2cgen +import 'sms_feature_vector.dart'; + +class RandomForestModel { + double score(SmsFeatureVector features) { + List input = [ + features.senderAgeScore, + features.senderInContacts ? 1.0 : 0.0, + features.senderMessageCount.toDouble(), + features.senderCarrierScore, + features.urgencyScore, + features.domainCount.toDouble(), + features.domainLevenshtein, + features.containsMoneyAction ? 1.0 : 0.0, + features.capsRatio, + features.hourOfDay.toDouble(), + features.isWeekend ? 1.0 : 0.0, + features.isFestivalPeriod ? 1.0 : 0.0, + features.recentScamSenderSim + ]; + List output = score_features(input); + // output[1] is the probability of class 1 (spam) + return output[1]; + } + + List score_features(List input) { + List var0; + if (input[4] <= 0.0555555559694767) { + if (input[12] <= 0.35010186582803726) { + var0 = [1.0, 0.0]; + } else { + var0 = [0.0, 1.0]; + } + } else { + if (input[12] <= 0.3311576470732689) { + var0 = [1.0, 0.0]; + } else { + var0 = [0.0, 1.0]; + } + } + List var1; + if (input[3] <= 0.499996542930603) { + var1 = [0.0, 1.0]; + } else { + var1 = [1.0, 0.0]; + } + List var2; + if (input[6] <= 0.9498419761657715) { + var2 = [0.0, 1.0]; + } else { + if (input[10] <= 0.5) { + if (input[3] <= 0.499612495303154) { + var2 = [0.0, 1.0]; + } else { + var2 = [1.0, 0.0]; + } + } else { + if (input[5] <= 0.5) { + if (input[2] <= 6.0) { + var2 = [0.0, 1.0]; + } else { + var2 = [1.0, 0.0]; + } + } else { + var2 = [1.0, 0.0]; + } + } + } + List var3; + if (input[6] <= 0.9498419761657715) { + var3 = [0.0, 1.0]; + } else { + if (input[12] <= 0.3500145226716995) { + var3 = [1.0, 0.0]; + } else { + var3 = [0.0, 1.0]; + } + } + List var4; + if (input[12] <= 0.3500145226716995) { + var4 = [1.0, 0.0]; + } else { + var4 = [0.0, 1.0]; + } + List var5; + if (input[2] <= 6.0) { + var5 = [0.0, 1.0]; + } else { + var5 = [1.0, 0.0]; + } + List var6; + if (input[6] <= 0.9498419761657715) { + var6 = [0.0, 1.0]; + } else { + if (input[3] <= 0.5000272989273071) { + var6 = [0.0, 1.0]; + } else { + var6 = [1.0, 0.0]; + } + } + List var7; + if (input[1] <= 0.5) { + if (input[4] <= 0.0555555559694767) { + if (input[3] <= 0.5000272989273071) { + var7 = [0.0, 1.0]; + } else { + var7 = [1.0, 0.0]; + } + } else { + var7 = [0.0, 1.0]; + } + } else { + var7 = [1.0, 0.0]; + } + List var8; + if (input[4] <= 0.0555555559694767) { + if (input[12] <= 0.3501044064760208) { + var8 = [1.0, 0.0]; + } else { + var8 = [0.0, 1.0]; + } + } else { + var8 = [0.0, 1.0]; + } + List var9; + if (input[9] <= 6.0) { + var9 = [0.0, 1.0]; + } else { + if (input[9] <= 20.5) { + var9 = [1.0, 0.0]; + } else { + var9 = [0.0, 1.0]; + } + } + List var10; + if (input[0] <= 0.3999420404434204) { + var10 = [0.0, 1.0]; + } else { + var10 = [1.0, 0.0]; + } + List var11; + if (input[2] <= 6.0) { + var11 = [0.0, 1.0]; + } else { + var11 = [1.0, 0.0]; + } + List var12; + if (input[6] <= 0.9498419761657715) { + var12 = [0.0, 1.0]; + } else { + if (input[2] <= 6.0) { + var12 = [0.0, 1.0]; + } else { + var12 = [1.0, 0.0]; + } + } + List var13; + if (input[2] <= 6.0) { + var13 = [0.0, 1.0]; + } else { + var13 = [1.0, 0.0]; + } + List var14; + if (input[5] <= 0.5) { + if (input[0] <= 0.3999420404434204) { + var14 = [0.0, 1.0]; + } else { + var14 = [1.0, 0.0]; + } + } else { + if (input[0] <= 0.40004269778728485) { + var14 = [0.0, 1.0]; + } else { + var14 = [1.0, 0.0]; + } + } + return mulVectorNumber(addVectors(addVectors(addVectors(addVectors(addVectors(addVectors(addVectors(addVectors(addVectors(addVectors(addVectors(addVectors(addVectors(addVectors(var0, var1), var2), var3), var4), var5), var6), var7), var8), var9), var10), var11), var12), var13), var14), 0.06666666666666667); +} +List addVectors(List v1, List v2) { + List result = new List.filled(v1.length, 0.0); + for (int i = 0; i < v1.length; i++) { + result[i] = v1[i] + v2[i]; + } + return result; +} +List mulVectorNumber(List v1, double num) { + List result = new List.filled(v1.length, 0.0); + for (int i = 0; i < v1.length; i++) { + result[i] = v1[i] * num; + } + return result; +} + +} diff --git a/lib/kavacha/models/sms_feature_vector.dart b/lib/kavacha/models/sms_feature_vector.dart new file mode 100644 index 0000000000000000000000000000000000000000..a094ae2f436cda550ca20fab21faa6a0ac826ec7 --- /dev/null +++ b/lib/kavacha/models/sms_feature_vector.dart @@ -0,0 +1,36 @@ +class SmsFeatureVector { + // Sender features (4) + final double senderAgeScore; // 0=new number, 1=years old + final bool senderInContacts; // false = +1 risk + final int senderMessageCount; // first SMS ever = high risk + final double senderCarrierScore; // VoIP/unknown=0, major carrier=1 + + // Content features (5) + final double urgencyScore; // density of urgency keywords + final int domainCount; // URLs in message + final double domainLevenshtein; // 0=identical to known bank, 1=unrelated + final bool containsMoneyAction; // ₹ amount + action verb together + final double capsRatio; // ALL CAPS fraction + + // Temporal features (4) + final int hourOfDay; // 0-23, banks never SMS at 2am + final bool isWeekend; // banks don't send KYC on Sunday + final bool isFestivalPeriod; // Diwali/Holi scam surge flag + final double recentScamSenderSim; // sender similarity to recent scam senders + + SmsFeatureVector({ + required this.senderAgeScore, + required this.senderInContacts, + required this.senderMessageCount, + required this.senderCarrierScore, + required this.urgencyScore, + required this.domainCount, + required this.domainLevenshtein, + required this.containsMoneyAction, + required this.capsRatio, + required this.hourOfDay, + required this.isWeekend, + required this.isFestivalPeriod, + required this.recentScamSenderSim, + }); +} diff --git a/lib/kavacha/threat_pack/festival_calendar.dart b/lib/kavacha/threat_pack/festival_calendar.dart new file mode 100644 index 0000000000000000000000000000000000000000..be73728559884e94b486256f52d270e28a6b43c5 --- /dev/null +++ b/lib/kavacha/threat_pack/festival_calendar.dart @@ -0,0 +1,45 @@ +class FestivalWindow { + final String name; + final int month; + final int? dayStart; + final int? dayEnd; + final double multiplier; + final bool dynamic; + + const FestivalWindow( + this.name, { + this.month = 1, + this.dayStart, + this.dayEnd, + required this.multiplier, + this.dynamic = false, + }); + + bool contains(DateTime date) { + if (dynamic) return false; // In a full implementation, queries a remote API + if (date.month != month) return false; + if (dayStart != null && date.day < dayStart!) return false; + if (dayEnd != null && date.day > dayEnd!) return false; + return true; + } +} + +class FestivalCalendar { + // Scam volume spikes 340% during these windows + static const festivalWindows = [ + FestivalWindow('Diwali', month: 10, dayStart: 20, dayEnd: 31, multiplier: 3.4), + FestivalWindow('Holi', month: 3, dayStart: 20, dayEnd: 30, multiplier: 2.1), + FestivalWindow('Dussehra', month: 10, dayStart: 1, dayEnd: 15, multiplier: 1.8), + FestivalWindow('Election', dynamic: true, multiplier: 2.8), // simulated + FestivalWindow('Budget Day', month: 2, dayStart: 1, dayEnd: 3, multiplier: 2.2), + FestivalWindow('New Year', month: 1, dayStart: 1, dayEnd: 5, multiplier: 1.9), + ]; + + double getCurrentSensitivityMultiplier() { + final now = DateTime.now(); + for (final window in festivalWindows) { + if (window.contains(now)) return window.multiplier; + } + return 1.0; // baseline + } +} diff --git a/lib/kavacha/threat_pack/otp_context_verifier.dart b/lib/kavacha/threat_pack/otp_context_verifier.dart new file mode 100644 index 0000000000000000000000000000000000000000..0ac2fb4df24f13a92d63c9c6e7e117804239012f --- /dev/null +++ b/lib/kavacha/threat_pack/otp_context_verifier.dart @@ -0,0 +1,144 @@ +import '../models/kavacha_models.dart'; +import '../../services/storage_service.dart'; +import 'package:flutter/foundation.dart'; + +class OtpContextVerifier { + // ─── Static cross-reference (real-time, from AccessibilityBridge) ─────────── + + /// Map of known sender codes → expected app package + static const _senderToPackage = { + 'HDFCBK': 'com.hdfcbank.mobilebanking', + 'ICICIB': 'com.csam.icici.bank.imobile', + 'SBIINB': 'com.sbi.lotusintouch', + 'PAYTM': 'net.one97.paytm', + 'PHONEPE': 'com.phonepe.app', + 'GPAY': 'com.google.android.apps.nbu.paisa.user', + 'AMZNIN': 'in.amazon.mShop.android.shopping', + 'SWIGGY': 'in.swiggy.android', + 'ZOMATO': 'com.application.zomato', + }; + + static String? _lastOtpSender; + static DateTime? _lastOtpTime; + + /// Called by SmsReceiver / Kavacha when OTP SMS is received. + static void recordOtpReceived(String sender) { + _lastOtpSender = sender.toUpperCase(); + _lastOtpTime = DateTime.now(); + } + + /// Called by AccessibilityBridge on every foreground app change. + static void checkContext(String foregroundPackage) { + if (_lastOtpSender == null || _lastOtpTime == null) return; + + // OTP older than 5 minutes — no longer relevant + if (DateTime.now().difference(_lastOtpTime!).inMinutes > 5) { + _lastOtpSender = null; + return; + } + + // Allow SMS/messaging apps — user is just reading the OTP + if (foregroundPackage == 'com.android.mms' || + foregroundPackage == 'com.google.android.apps.messaging') { + return; + } + + final expectedPackage = _findExpectedPackage(_lastOtpSender!); + + if (expectedPackage == null) { + // Unknown sender — medium risk + _fireAlert( + level: 'MEDIUM', + message: 'OTP from unknown sender: $_lastOtpSender', + detail: 'Could not verify which app this OTP is for', + sender: _lastOtpSender!, + ); + return; + } + + if (foregroundPackage != expectedPackage) { + // Wrong app is open — high risk + _fireAlert( + level: 'HIGH', + message: 'OTP mismatch — possible phishing', + detail: + '$_lastOtpSender OTP arrived but a different app is in foreground', + sender: _lastOtpSender!, + ); + } + // Correct app is open — safe, no alert + } + + static String? _findExpectedPackage(String sender) { + for (final entry in _senderToPackage.entries) { + if (sender.contains(entry.key)) return entry.value; + } + return null; + } + + static void _fireAlert({ + required String level, + required String message, + required String detail, + required String sender, + }) { + debugPrint('[OtpContext] $level — $message'); + + // Log to scam_log + StorageService().insertScamLog({ + 'sender': sender, + 'message_preview': detail, + 'category': 'OTP Phishing', + 'confidence': level == 'HIGH' ? 0.92 : 0.72, + 'threat_level': level, + 'created_at': DateTime.now().millisecondsSinceEpoch, + }); + } + + // ─── Instance methods (existing — SMS pipeline layer) ──────────────────────── + + LayerResult verify(String smsBody, String foregroundApp) { + final otpSender = _extractOtpSender(smsBody); + if (otpSender == null) return LayerResult.pass(); + + if (_appMatchesSender(foregroundApp, otpSender)) return LayerResult.pass(); + + if (foregroundApp == 'launcher' && otpSender.toLowerCase().contains('bank')) { + return LayerResult.block( + 'OTP arrived with no banking app open', 0.95, ['otp_no_context_bank']); + } + + if (!_isKnownSender(otpSender)) { + return LayerResult.block( + 'OTP from unrecognised service: $otpSender', 0.85, ['otp_unrecognised_service']); + } + + return LayerResult.pass(); + } + + String? _extractOtpSender(String body) { + if (body.toLowerCase().contains('otp') || + body.toLowerCase().contains('one time password')) { + final words = body.split(' '); + if (words.isNotEmpty && + words[0].length >= 4 && + words[0].toUpperCase() == words[0]) { + return words[0]; + } + return 'UNKNOWN_SENDER'; + } + return null; + } + + bool _appMatchesSender(String app, String sender) => + sender.toLowerCase().contains(app.toLowerCase()); + + bool _isKnownSender(String sender) => [ + 'HDFCBK', + 'ICICI', + 'SBIN', + 'PAYTM', + 'GPAY', + 'PHONPE', + ].contains(sender.toUpperCase()); +} diff --git a/lib/kavacha/threat_pack/outgoing_data_shield.dart b/lib/kavacha/threat_pack/outgoing_data_shield.dart new file mode 100644 index 0000000000000000000000000000000000000000..292535b961bac990dc6801d27d9221ce4a26a418 --- /dev/null +++ b/lib/kavacha/threat_pack/outgoing_data_shield.dart @@ -0,0 +1,35 @@ +class ShieldResult { + final bool isSafe; + final String? warningTitle; + final String? warningMessage; + + ShieldResult.safe() : isSafe = true, warningTitle = null, warningMessage = null; + ShieldResult.warn(this.warningTitle, this.warningMessage) : isSafe = false; +} + +class OutgoingDataShield { + static final _aadhaarPattern = RegExp(r'\b\d{4}\s?\d{4}\s?\d{4}\b'); + static final _panPattern = RegExp(r'\b[A-Z]{5}[0-9]{4}[A-Z]\b'); + static final _bankAccPattern = RegExp(r'\b\d{9,18}\b'); + + // Called from KeyboardIMEService before commitText() + ShieldResult check(String outgoingText) { + if (_aadhaarPattern.hasMatch(outgoingText)) { + return ShieldResult.warn( + 'Aadhaar number detected in outgoing message', + 'Are you sure you want to share this?', + ); + } + if (_panPattern.hasMatch(outgoingText)) { + return ShieldResult.warn('PAN number detected', 'Verify recipient before sending'); + } + // Very simple fallback, real implementation would run luhn checks + if (_bankAccPattern.hasMatch(outgoingText) && outgoingText.length >= 9 && outgoingText.length <= 18) { + // Too broad if just digits, we add a simple check + if (outgoingText.startsWith('0') || outgoingText.length >= 11) { + return ShieldResult.warn('Bank account number detected', 'Share only with trusted contacts'); + } + } + return ShieldResult.safe(); + } +} diff --git a/lib/kavacha/threat_pack/upi_firewall.dart b/lib/kavacha/threat_pack/upi_firewall.dart new file mode 100644 index 0000000000000000000000000000000000000000..c382764f4600ae8f74f8cd49f59ef10105d8c01d --- /dev/null +++ b/lib/kavacha/threat_pack/upi_firewall.dart @@ -0,0 +1,54 @@ +import '../models/kavacha_models.dart'; + +class UpiFirewall { + static const trustedVpaSuffixes = [ + '@hdfcbank', '@sbi', '@icici', '@axisbank', + '@ybl', '@oksbi', '@okicici', '@paytm', + ]; + + LayerResult analyze(String message) { + // Rule 1: Rs.1 collect request = classic fraud + if (_matchesRupeeCollect(message, maxAmount: 1)) { + return LayerResult.block('UPI Collect Fraud — ₹1 trick', 0.99, ["upi_1_rs_trick"]); + } + + // Rule 2: Unknown VPA suffix + final vpa = _extractVpa(message); + if (vpa != null && !_isTrustedVpa(vpa)) { + return LayerResult.block('Unknown UPI address: \$vpa', 0.85, ["unknown_vpa", vpa]); + } + + // Rule 3: QR code in message with urgency language + if (_hasQrCode(message) && _hasUrgencyLanguage(message)) { + return LayerResult.block('Suspicious QR + urgency', 0.90, ["qr_urgency"]); + } + + return LayerResult.pass(); + } + + bool _matchesRupeeCollect(String message, {required int maxAmount}) { + final lower = message.toLowerCase(); + return (lower.contains('rs.1') || lower.contains('₹1') || lower.contains('amount: 1')) && + (lower.contains('collect') || lower.contains('request') || lower.contains('pay')); + } + + String? _extractVpa(String message) { + final RegExp vpaRegex = RegExp(r'[a-zA-Z0-9.\-_]{2,256}@[a-zA-Z]{2,64}'); + final match = vpaRegex.firstMatch(message); + return match?.group(0); + } + + bool _isTrustedVpa(String vpa) { + final lowerVpa = vpa.toLowerCase(); + return trustedVpaSuffixes.any((suffix) => lowerVpa.endsWith(suffix)); + } + + bool _hasQrCode(String message) { + return message.toLowerCase().contains('scan this qr') || message.toLowerCase().contains('qr code'); + } + + bool _hasUrgencyLanguage(String message) { + final lower = message.toLowerCase(); + return lower.contains('urgent') || lower.contains('immediate') || lower.contains('blocked'); + } +} diff --git a/lib/keyboard/hinglish_ngram.dart b/lib/keyboard/hinglish_ngram.dart new file mode 100644 index 0000000000000000000000000000000000000000..5791721e2471ca888c9a3173116ae4509667d02a --- /dev/null +++ b/lib/keyboard/hinglish_ngram.dart @@ -0,0 +1,61 @@ +enum Language { hindi, english, unknown } + +class HinglishNgram { + // Mock implementations for hackathon scale as per PRD + static final _hindiRomanPatterns = [ + RegExp(r'\bhain\b'), + RegExp(r'\bkaise\b'), + RegExp(r'\bkaam\b'), + RegExp(r'\bkya\b'), + RegExp(r'\bkaro\b'), + RegExp(r'\bnahi\b'), + ]; + + static final _englishDictionary = {'the', 'is', 'are', 'what', 'how', 'do', 'not'}; + + static final Map> _bigramModel = { + 'kya': ['hua', 'hai', 'kar'], + 'kaise': ['ho', 'hai', 'kare'], + 'the': ['best', 'good', 'way'], + 'how': ['are', 'is', 'to'], + }; + + static final Map> _trigramModel = { + 'kya hal': ['hai'], + 'how are': ['you'], + }; + + static final Map _translitMap = { + 'namaste': 'नमस्ते', + 'kya': 'क्या', + 'hai': 'है', + 'kaise': 'कैसे', + 'ho': 'हो', + }; + + Language detectLanguage(String word) { + if (_hindiRomanPatterns.any((p) => p.hasMatch(word.toLowerCase()))) return Language.hindi; + if (_englishDictionary.contains(word.toLowerCase())) return Language.english; + return Language.unknown; + } + + List suggest(String context, {int n = 3}) { + if (context.isEmpty) return ['kya', 'hai', 'the']; // Defaults + + final tokens = context.toLowerCase().trim().split(' '); + + if (tokens.length >= 2) { + final lastTwo = tokens.skip(tokens.length - 2).join(' '); + if (_trigramModel.containsKey(lastTwo)) return _trigramModel[lastTwo]!; + } + + if (tokens.isNotEmpty) { + final last = tokens.last; + if (_bigramModel.containsKey(last)) return _bigramModel[last]!; + } + + return []; + } + + String? transliterate(String roman) => _translitMap[roman.toLowerCase()]; +} diff --git a/lib/keyboard/keyboard_channel.dart b/lib/keyboard/keyboard_channel.dart new file mode 100644 index 0000000000000000000000000000000000000000..cc49d12f4f639b88717c9878b85e18c151f948ac --- /dev/null +++ b/lib/keyboard/keyboard_channel.dart @@ -0,0 +1,26 @@ +import 'package:flutter/services.dart'; + +class KeyboardChannel { + static const MethodChannel _channel = MethodChannel('in.inmodel.premithus/keyboard'); + + static Future commitText(String text) async { + await _channel.invokeMethod('commitText', {'text': text}); + } + + static Future deleteBackward() async { + await _channel.invokeMethod('deleteBackward'); + } + + static Future replaceText(String newText) async { + await _channel.invokeMethod('replaceText', {'text': newText}); + } + + static Future getText() async { + final String? text = await _channel.invokeMethod('getText'); + return text ?? ''; + } + + static Future hideKeyboard() async { + await _channel.invokeMethod('hideKeyboard'); + } +} diff --git a/lib/keyboard/keyboard_layout.dart b/lib/keyboard/keyboard_layout.dart new file mode 100644 index 0000000000000000000000000000000000000000..0fda1a6334c9dece725495ac822d1f06e9baf0ab --- /dev/null +++ b/lib/keyboard/keyboard_layout.dart @@ -0,0 +1,165 @@ +import 'package:flutter/material.dart'; +import 'package:virtual_keyboard_multi_language/virtual_keyboard_multi_language.dart'; +import 'package:google_fonts/google_fonts.dart'; +import '../services/grammar_service.dart'; +import '../services/llm_service.dart'; +import '../services/storage_service.dart'; +import '../kavacha/threat_pack/outgoing_data_shield.dart'; +import 'hinglish_ngram.dart'; +import 'keyboard_channel.dart'; +import 'shortcut_bar.dart'; + +class PremithiusKeyboard extends StatefulWidget { + const PremithiusKeyboard({Key? key}) : super(key: key); + + @override + _PremithiusKeyboardState createState() => _PremithiusKeyboardState(); +} + +class _PremithiusKeyboardState extends State { + bool _isGenerating = false; + final _grammarService = GrammarService(); + final _llmService = LlmService(); + final _storageService = StorageService(); + final _outgoingShield = OutgoingDataShield(); + final _hinglish = HinglishNgram(); + + @override + void initState() { + super.initState(); + _grammarService.init(); + } + + Future _onShortcutAction(String action) async { + setState(() => _isGenerating = true); + + // Fetch current text from IME + String originalText = await KeyboardChannel.getText(); + String newText = originalText; + + if (action == 'Fix') { + newText = await _grammarService.fixGrammar(originalText); + } else { + newText = await _llmService.processAction(originalText, action); + } + + await KeyboardChannel.replaceText(newText); + + // Log asynchronously + try { + await _storageService.insertKeyboardLog({ + 'app_context': 'premithus_ime', // Default context + 'original_text': originalText, + 'action': action, + 'result_text': newText, + 'accepted': 1, + 'created_at': DateTime.now().millisecondsSinceEpoch, + }); + } catch (e) { + debugPrint('Error inserting keyboard log: \$e'); + } + + if (mounted) { + setState(() => _isGenerating = false); + } + } + + void _onKeyPress(VirtualKeyboardKey key) async { + if (key.keyType == VirtualKeyboardKeyType.String) { + KeyboardChannel.commitText(key.text ?? ''); + } else if (key.keyType == VirtualKeyboardKeyType.Action) { + switch (key.action) { + case VirtualKeyboardKeyAction.Backspace: + KeyboardChannel.deleteBackward(); + break; + case VirtualKeyboardKeyAction.Space: + case VirtualKeyboardKeyAction.Return: + // Check for data leaks on word boundaries + String fullText = await KeyboardChannel.getText(); + final shieldResult = _outgoingShield.check(fullText); + + if (!shieldResult.isSafe) { + // In a real app we would show a confirmation dialog or red overlay + debugPrint("SHIELD WARNING: \${shieldResult.warningTitle}"); + // Simulate temporary block + ScaffoldMessenger.of(context).showSnackBar( + SnackBar(content: Text(shieldResult.warningMessage ?? "Blocked"), backgroundColor: Colors.red), + ); + } else { + KeyboardChannel.commitText(key.action == VirtualKeyboardKeyAction.Space ? ' ' : '\n'); + } + break; + default: + break; + } + } + } + + @override + Widget build(BuildContext context) { + return Material( + color: Colors.black, + child: Column( + mainAxisSize: MainAxisSize.min, + children: [ + Container( + padding: const EdgeInsets.symmetric(horizontal: 16, vertical: 4), + decoration: BoxDecoration( + color: Colors.black54, + border: Border(bottom: BorderSide(color: Colors.white.withValues(alpha: 0.05))), + ), + child: Row( + mainAxisAlignment: MainAxisAlignment.spaceBetween, + children: [ + Row( + children: [ + const Icon(Icons.shield_rounded, color: Colors.blueAccent, size: 14), + const SizedBox(width: 6), + Text( + "KAVACHA PROTECTED", + style: GoogleFonts.outfit( + color: Colors.blueAccent, + fontSize: 10, + fontWeight: FontWeight.w800, + letterSpacing: 1.1, + ), + ), + ], + ), + Container( + padding: const EdgeInsets.symmetric(horizontal: 8, vertical: 2), + decoration: BoxDecoration( + color: Colors.greenAccent.withValues(alpha: 0.1), + borderRadius: BorderRadius.circular(4), + ), + child: Text( + "SAFE", + style: GoogleFonts.outfit( + color: Colors.greenAccent, + fontSize: 10, + fontWeight: FontWeight.bold, + ), + ), + ), + ], + ), + ), + ShortcutBar( + onAction: _onShortcutAction, + isGenerating: _isGenerating, + ), + Container( + color: Colors.black, + child: VirtualKeyboard( + height: 250, + textColor: Colors.white, + type: VirtualKeyboardType.Alphanumeric, + textController: TextEditingController(), + postKeyPress: _onKeyPress, + ), + ), + ], + ), + ); + } +} diff --git a/lib/keyboard/shortcut_bar.dart b/lib/keyboard/shortcut_bar.dart new file mode 100644 index 0000000000000000000000000000000000000000..90cd3dad93e28261ff112c687da53839ce6ffb1b --- /dev/null +++ b/lib/keyboard/shortcut_bar.dart @@ -0,0 +1,152 @@ +import 'package:flutter/material.dart'; +import 'package:google_fonts/google_fonts.dart'; +import 'package:flutter_animate/flutter_animate.dart'; +import '../services/accessibility_service.dart'; + +class ShortcutBar extends StatefulWidget { + final Future Function(String action) onAction; + final bool isGenerating; + + const ShortcutBar({ + Key? key, + required this.onAction, + this.isGenerating = false, + }) : super(key: key); + + @override + State createState() => _ShortcutBarState(); +} + +class _ShortcutBarState extends State { + @override + void initState() { + super.initState(); + AccessibilityBridge.addToneListener(_onToneChanged); + } + + @override + void dispose() { + AccessibilityBridge.removeToneListener(_onToneChanged); + super.dispose(); + } + + void _onToneChanged() { + if (mounted) setState(() {}); + } + + String get _contextLabel { + final app = AccessibilityBridge.currentAppName; + final tone = AccessibilityBridge.currentToneContext; + if (app.isEmpty || tone == 'neutral') return ''; + final toneLabel = tone[0].toUpperCase() + tone.substring(1); + return '$app — $toneLabel mode'; + } + + @override + Widget build(BuildContext context) { + final label = _contextLabel; + + return Column( + mainAxisSize: MainAxisSize.min, + children: [ + // ── Tone context hint ─────────────────────────────────── + if (label.isNotEmpty) + Container( + width: double.infinity, + color: Colors.black.withValues(alpha: 0.9), + padding: const EdgeInsets.symmetric(horizontal: 14, vertical: 3), + child: Text( + label, + style: GoogleFonts.outfit( + color: Colors.white38, + fontSize: 10.5, + fontStyle: FontStyle.italic, + ), + ), + ), + // ── Shortcut buttons ──────────────────────────────────── + Container( + height: 56, + decoration: BoxDecoration( + color: Colors.black.withValues(alpha: 0.8), + border: Border( + bottom: BorderSide( + color: Colors.white.withValues(alpha: 0.1), width: 0.5), + ), + ), + child: widget.isGenerating + ? Center( + child: const Text( + "PREMITHIUS GENERATING...", + style: TextStyle( + color: Colors.blueAccent, + letterSpacing: 1.2, + fontSize: 10, + fontWeight: FontWeight.bold, + ), + ) + .animate(onPlay: (controller) => controller.repeat()) + .fadeIn(duration: 400.ms) + .then() + .shimmer(duration: 1200.ms, color: Colors.white24) + .fadeOut(delay: 800.ms, duration: 400.ms), + ) + : ListView( + scrollDirection: Axis.horizontal, + padding: + const EdgeInsets.symmetric(horizontal: 8, vertical: 10), + children: [ + _buildButton("Fix", Colors.blueAccent, Icons.auto_fix_high), + _buildButton( + "Formal", Colors.indigoAccent, Icons.business_center), + _buildButton("Casual", Colors.tealAccent, Icons.coffee), + _buildButton("Short", Colors.amberAccent, Icons.compress), + _buildButton( + "Sum", Colors.deepOrangeAccent, Icons.summarize), + ], + ), + ), + ], + ); + } + + Widget _buildButton(String label, Color color, IconData icon) { + return Padding( + padding: const EdgeInsets.symmetric(horizontal: 4.0), + child: InkWell( + onTap: () => widget.onAction(label), + borderRadius: BorderRadius.circular(12), + child: Container( + padding: const EdgeInsets.symmetric(horizontal: 14), + decoration: BoxDecoration( + gradient: LinearGradient( + colors: [ + color.withValues(alpha: 0.15), + color.withValues(alpha: 0.05), + ], + begin: Alignment.topLeft, + end: Alignment.bottomRight, + ), + borderRadius: BorderRadius.circular(12), + border: Border.all(color: color.withValues(alpha: 0.3), width: 1), + ), + child: Row( + mainAxisSize: MainAxisSize.min, + children: [ + Icon(icon, size: 16, color: color), + const SizedBox(width: 8), + Text( + label, + style: GoogleFonts.outfit( + color: color, + fontWeight: FontWeight.w600, + fontSize: 13, + ), + ), + ], + ), + ), + ), + ); + } +} diff --git a/lib/main.dart b/lib/main.dart new file mode 100644 index 0000000000000000000000000000000000000000..8ea1674f925d0586bbb47f7360706d1025d985ec --- /dev/null +++ b/lib/main.dart @@ -0,0 +1,73 @@ +import 'package:flutter/material.dart'; +import 'package:flutter/services.dart'; +import 'keyboard/keyboard_layout.dart'; +import 'onboarding/permission_flow.dart'; +import 'services/scam_service.dart'; +import 'theme/finanjo_theme.dart'; + +void main() { + WidgetsFlutterBinding.ensureInitialized(); + AccessibilityBridge.initialize(); + runApp(const PremithiusApp()); +} + +/// A specific entrypoint for the Android IME Service. +/// The IME Service will call DartExecutor.DartEntrypoint(..., "keyboardMain") +@pragma('vm:entry-point') +void keyboardMain() { + runApp(const MaterialApp( + debugShowCheckedModeBanner: false, + home: PremithiusKeyboard(), + )); +} + +@pragma('vm:entry-point') +void scamMain() { + // Headless execution for handling SMS analysis requests + WidgetsFlutterBinding.ensureInitialized(); + const channel = MethodChannel('in.inmodel.premithus/scam'); + + // Need to initialize ScamService without UI + final scamService = ScamService(); + scamService.init(); + + channel.setMethodCallHandler((call) async { + if (call.method == 'analyze') { + final String sender = call.arguments['sender'] ?? ''; + final String messageBody = call.arguments['messageBody'] ?? ''; + + final result = await scamService.analyzeSms(sender, messageBody); + + return { + 'isScam': result.isScam, + 'category': result.category, + 'confidence': result.confidence, + 'threatLevel': result.threatLevel, + 'triggeredLayer': result.triggeredLayer, + 'layerLabel': result.layerLabel, + }; + } else if (call.method == 'feedback') { + final String sender = call.arguments['sender'] ?? ''; + final String messageBody = call.arguments['messageBody'] ?? ''; + final bool isScam = call.arguments['isScam'] ?? false; + + await scamService.processFeedback(sender, messageBody, isScam); + return null; + } + return null; + }); +} + +class PremithiusApp extends StatelessWidget { + const PremithiusApp({Key? key}) : super(key: key); + + @override + Widget build(BuildContext context) { + return MaterialApp( + title: 'Premithius', + theme: FinanjoTheme.themeData, + // Default to Permission Flow on first launch + home: const PermissionFlow(), + ); + } +} diff --git a/lib/onboarding/model_download.dart b/lib/onboarding/model_download.dart new file mode 100644 index 0000000000000000000000000000000000000000..75d31c38f1ac300df8cdd3399d1b61f5f61797e3 --- /dev/null +++ b/lib/onboarding/model_download.dart @@ -0,0 +1,203 @@ +import 'package:flutter/material.dart'; +import 'package:path_provider/path_provider.dart'; +import 'dart:io'; +import '../theme/finanjo_theme.dart'; +import '../screens/dashboard/home_dashboard.dart'; +import 'package:flutter_animate/flutter_animate.dart'; + +class ModelDownloadScreen extends StatefulWidget { + const ModelDownloadScreen({Key? key}) : super(key: key); + + @override + _ModelDownloadScreenState createState() => _ModelDownloadScreenState(); +} + +class _ModelDownloadScreenState extends State { + double _progress = 0.0; + bool _isDownloading = false; + bool _isComplete = false; + + @override + void initState() { + super.initState(); + _checkModelExists(); + } + + Future _checkModelExists() async { + final docDir = await getApplicationDocumentsDirectory(); + final modelDir = Directory('${docDir.path}/models'); + if (!modelDir.existsSync()) { + modelDir.createSync(recursive: true); + } + final modelPath = '${modelDir.path}/qwen2.gguf'; + + if (File(modelPath).existsSync()) { + setState(() { + _isComplete = true; + }); + _finish(); + } + } + + Future _startDownload() async { + setState(() { + _isDownloading = true; + _progress = 0.0; + }); + + final docDir = await getApplicationDocumentsDirectory(); + final modelPath = '${docDir.path}/models/qwen2.gguf'; + final file = File(modelPath); + + try { + final client = HttpClient(); + final request = await client.getUrl(Uri.parse( + 'https://huggingface.co/Qwen/Qwen1.5-0.5B-Chat-GGUF/resolve/main/qwen1_5-0_5b-chat-q4_k_m.gguf')); + final response = await request.close(); + + final contentLength = response.contentLength; + int downloadedBytes = 0; + final sink = file.openWrite(); + + await response.forEach((chunk) { + sink.add(chunk); + downloadedBytes += chunk.length; + if (contentLength > 0 && mounted) { + setState(() { + _progress = downloadedBytes / contentLength; + }); + } + }); + await sink.close(); + + if (mounted) { + setState(() { + _isDownloading = false; + _isComplete = true; + }); + } + _finish(); + } catch (e) { + if (mounted) { + setState(() { + _isDownloading = false; + }); + ScaffoldMessenger.of(context).showSnackBar( + SnackBar(content: Text('Download failed: $e')), + ); + } + } + } + + void _finish() { + Future.delayed(const Duration(seconds: 1), () { + if (mounted) { + Navigator.pushReplacement( + context, + MaterialPageRoute(builder: (context) => const HomeDashboard()), + ); + } + }); + } + + @override + Widget build(BuildContext context) { + return Scaffold( + body: Container( + decoration: const BoxDecoration( + gradient: FinanjoTheme.premiumGradient, + ), + child: SafeArea( + child: Center( + child: SingleChildScrollView( + child: Column( + mainAxisAlignment: MainAxisAlignment.center, + children: [ + // App Icon / Logo + const CircleAvatar( + radius: 40, + backgroundColor: FinanjoTheme.lightPurple, + child: Icon(Icons.smart_toy, size: 48, color: FinanjoTheme.primaryPurple), + ).animate().scale(duration: 600.ms, curve: Curves.easeOutBack).fadeIn(duration: 600.ms), + const SizedBox(height: 32), + const Text( + 'Downloading\nAI Engine', + textAlign: TextAlign.center, + style: FinanjoTheme.headingStyle, + ).animate().fadeIn(delay: 200.ms, duration: 600.ms).slideY(begin: 0.2, end: 0, curve: Curves.easeOutQuad), + const SizedBox(height: 16), + + // Main Card + Container( + width: double.infinity, + margin: const EdgeInsets.symmetric(horizontal: 24, vertical: 16), + padding: const EdgeInsets.all(32), + decoration: FinanjoTheme.cardDecoration, + child: Column( + crossAxisAlignment: CrossAxisAlignment.stretch, + children: [ + if (!_isDownloading && !_isComplete) ...[ + const Text( + 'Premithius needs to download the AI model to guarantee on-device privacy. This will happen over Wi-Fi only.', + textAlign: TextAlign.center, + style: FinanjoTheme.bodyStyle, + ), + const SizedBox(height: 32), + ElevatedButton( + style: FinanjoTheme.primaryButtonStyle, + onPressed: _startDownload, + child: const Text('Download Now'), + ), + ], + + if (_isDownloading) ...[ + const Text( + 'Downloading Secure AI Model...', + textAlign: TextAlign.center, + style: FinanjoTheme.subHeadingStyle, + ), + const SizedBox(height: 24), + // Premium progress indicator + ClipRRect( + borderRadius: BorderRadius.circular(8), + child: LinearProgressIndicator( + value: _progress, + minHeight: 12, + backgroundColor: FinanjoTheme.lightPurple.withOpacity(0.3), + valueColor: const AlwaysStoppedAnimation(FinanjoTheme.primaryPurple), + ), + ).animate().fadeIn(duration: 300.ms), + const SizedBox(height: 16), + Text( + '${(_progress * 100).toStringAsFixed(0)}%', + textAlign: TextAlign.center, + style: FinanjoTheme.headingStyle.copyWith( + fontSize: 24, + color: FinanjoTheme.primaryPurple, + ), + ), + ], + + if (_isComplete) ...[ + const Icon(Icons.check_circle, color: FinanjoTheme.successGreen, size: 64) + .animate() + .scale(duration: 500.ms, curve: Curves.elasticOut), + const SizedBox(height: 16), + Text( + 'Model Downloaded', + textAlign: TextAlign.center, + style: FinanjoTheme.headingStyle.copyWith(fontSize: 20), + ).animate().fadeIn(delay: 200.ms), + ], + ], + ), + ).animate().fadeIn(delay: 400.ms, duration: 800.ms).slideY(begin: 0.1, end: 0, curve: Curves.easeOutCubic), + ], + ), + ), + ), + ), + ), + ); + } +} diff --git a/lib/onboarding/permission_flow.dart b/lib/onboarding/permission_flow.dart new file mode 100644 index 0000000000000000000000000000000000000000..eb77a11559bc49c00a47657cb38d03761a35279c --- /dev/null +++ b/lib/onboarding/permission_flow.dart @@ -0,0 +1,189 @@ +import 'dart:async'; +import 'package:flutter/material.dart'; +import 'package:flutter/services.dart'; +import 'package:permission_handler/permission_handler.dart'; +import 'model_download.dart'; +import '../theme/finanjo_theme.dart'; +import 'package:flutter_animate/flutter_animate.dart'; + +class PermissionFlow extends StatefulWidget { + const PermissionFlow({super.key}); + + @override + _PermissionFlowState createState() => _PermissionFlowState(); +} + +import '../services/telemetry_service.dart'; + +// ... +class _PermissionFlowState extends State { + int _step = 0; // 0=SMS, 1=Overlay, 2=Accessibility, 3=VPN, 4=UsageStats + bool _isPollingA11y = false; + Timer? _a11yTimer; + + bool _isPollingUsage = false; + Timer? _usageTimer; + + @override + void dispose() { + _a11yTimer?.cancel(); + _usageTimer?.cancel(); + super.dispose(); + } + + // ─── Step 0: SMS ───────────────────────────────────────────────────────────── + Future _requestSms() async { + if (!await Permission.sms.request().isGranted) return; + setState(() => _step = 1); + } + + // ─── Step 1: Overlay ───────────────────────────────────────────────────────── + Future _requestOverlay() async { + if (!await Permission.systemAlertWindow.request().isGranted) return; + await Permission.notification.request(); + setState(() => _step = 2); + } + + // ─── Step 2: Accessibility ─────────────────────────────────────────────────── + Future _openAccessibilitySettings() async { + try { + const channel = MethodChannel('in.inmodel.premithus/accessibility'); + await channel.invokeMethod('openAccessibilitySettings'); + } catch (_) { + // Channel not yet configured → system fallback + } + + // On Android we can open accessibility settings via platform + const platform = MethodChannel('flutter/platform_channel'); + try { + await platform.invokeMethod('openSettingsIntent', 'android.settings.ACCESSIBILITY_SETTINGS'); + } catch (_) {} + + // Poll every 2 seconds for the service to be enabled + if (!_isPollingA11y) { + _isPollingA11y = true; + _a11yTimer = Timer.periodic(const Duration(seconds: 2), (timer) async { + final enabled = await AccessibilityBridge.isServiceEnabled(); + if (enabled && mounted) { + timer.cancel(); + setState(() => _step = 3); + } + }); + } + } + + // ─── Step 3: VPN Shield ────────────────────────────────────────────────────── + Future _requestVpn() async { + await KavachaVpn.start(); + setState(() => _step = 4); + } + + void _skipVpn() { + setState(() => _step = 4); + } + + // ─── Step 4: Usage Stats ────────────────────────────────────────────────────── + Future _requestUsageStats() async { + const platform = MethodChannel('flutter/platform_channel'); + try { + await platform.invokeMethod('openSettingsIntent', 'android.settings.USAGE_ACCESS_SETTINGS'); + } catch (_) {} + + if (!_isPollingUsage) { + _isPollingUsage = true; + _usageTimer = Timer.periodic(const Duration(seconds: 2), (timer) async { + final enabled = await TelemetryService.hasUsagePermission(); + if (enabled && mounted) { + timer.cancel(); + _advance(); + } + }); + } + } + + void _skipUsageStats() { + _advance(); + } + + void _advance() { + if (!mounted) return; + Navigator.pushReplacement( + context, + MaterialPageRoute(builder: (_) => const DataShieldScreen()), + ); + } + + @override + Widget build(BuildContext context) { + return Scaffold( + body: Container( + decoration: const BoxDecoration( + gradient: FinanjoTheme.premiumGradient, + ), + child: SafeArea( + child: Column( + children: [ + const SizedBox(height: 60), + // Header + Padding( + padding: const EdgeInsets.symmetric(horizontal: 24.0), + child: Column( + children: [ + const Icon( + Icons.shield_outlined, + size: 64, + color: FinanjoTheme.primaryPurple, + ).animate().fadeIn(duration: 600.ms).slideY(begin: 0.2, end: 0, curve: Curves.easeOutQuad), + const SizedBox(height: 24), + const Text( + 'Your Device\nFully Secure', + textAlign: TextAlign.center, + style: FinanjoTheme.headingStyle, + ).animate().fadeIn(delay: 150.ms, duration: 600.ms).slideY(begin: 0.2, end: 0, curve: Curves.easeOutQuad), + const SizedBox(height: 12), + const Text( + 'AI-powered protection right from your keyboard.', + textAlign: TextAlign.center, + style: FinanjoTheme.subHeadingStyle, + ).animate().fadeIn(delay: 300.ms, duration: 600.ms).slideY(begin: 0.2, end: 0, curve: Curves.easeOutQuad), + ], + ), + ), + const Spacer(), + // White Card + Container( + width: double.infinity, + margin: const EdgeInsets.all(24), + padding: const EdgeInsets.all(32), + decoration: FinanjoTheme.cardDecoration, + child: Column( + crossAxisAlignment: CrossAxisAlignment.stretch, + children: [ + const Icon( + Icons.security, + size: 48, + color: FinanjoTheme.cautionYellow, + ), + const SizedBox(height: 24), + const Text( + 'We need a few permissions to actively protect you from scams and unwanted messages.', + textAlign: TextAlign.center, + style: FinanjoTheme.bodyStyle, + ), + const SizedBox(height: 32), + ElevatedButton( + style: FinanjoTheme.primaryButtonStyle, + onPressed: requestPermissions, + child: const Text('Grant Permissions'), + ), + ], + ), + ).animate().fadeIn(delay: 450.ms, duration: 800.ms).slideY(begin: 0.1, end: 0, curve: Curves.easeOutCubic), + const SizedBox(height: 20), + ], + ), + ), + ), + ); + } +} diff --git a/lib/screens/app_lock_screen.dart b/lib/screens/app_lock_screen.dart new file mode 100644 index 0000000000000000000000000000000000000000..d7cdfebdac893416d5a057296a9797701865c7af --- /dev/null +++ b/lib/screens/app_lock_screen.dart @@ -0,0 +1,242 @@ +import 'dart:async'; +import 'package:flutter/material.dart'; +import 'package:flutter/services.dart'; +import 'package:google_fonts/google_fonts.dart'; +import '../services/app_lock_service.dart'; +import '../services/accessibility_service.dart'; +import '../services/storage_service.dart'; + +class AppLockScreen extends StatefulWidget { + const AppLockScreen({super.key}); + + @override + State createState() => _AppLockScreenState(); +} + +class _AppLockScreenState extends State { + List _installedApps = []; + Set _lockedPackages = {}; + Map _attemptCounts = {}; + bool _isAccessibilityEnabled = false; + bool _loading = true; + + @override + void initState() { + super.initState(); + _loadData(); + } + + Future _loadData() async { + final [apps, locked, enabled] = await Future.wait([ + AppLockService.getInstalledApps(), + AppLockService.getLockedApps(), + AccessibilityBridge.isServiceEnabled(), + ]); + + // Build attempt count map + final storage = StorageService(); + final Map counts = {}; + for (final la in locked as List) { + counts[la.packageName] = + await storage.getAccessAttemptsTodayCount(la.packageName); + } + + if (mounted) { + setState(() { + _installedApps = List.from(apps as List); + _installedApps.sort((a, b) => a.appName.compareTo(b.appName)); + _lockedPackages = + (locked as List).map((e) => e.packageName).toSet(); + _attemptCounts = counts; + _isAccessibilityEnabled = enabled as bool; + _loading = false; + }); + } + } + + Future _toggleLock(InstalledApp app, bool lock) async { + if (lock) { + await AppLockService.lockApp(app.packageName, app.appName); + } else { + await AppLockService.unlockApp(app.packageName); + } + setState(() { + if (lock) { + _lockedPackages.add(app.packageName); + } else { + _lockedPackages.remove(app.packageName); + _attemptCounts.remove(app.packageName); + } + }); + } + + void _openAccessibilitySettings() { + const platform = MethodChannel('in.inmodel.premithus/accessibility'); + // Fall back: just open accessibility settings action + try { + platform.invokeMethod('openAccessibilitySettings'); + } catch (_) { + // Handled by OS default + } + // Poll for enable after settings + Timer.periodic(const Duration(seconds: 2), (timer) async { + final enabled = await AccessibilityBridge.isServiceEnabled(); + if (enabled && mounted) { + timer.cancel(); + setState(() => _isAccessibilityEnabled = true); + } + }); + } + + @override + Widget build(BuildContext context) { + return Scaffold( + backgroundColor: const Color(0xFF0D0D1A), + appBar: AppBar( + backgroundColor: const Color(0xFF0D0D1A), + title: Row( + children: [ + const Icon(Icons.lock_outline, color: Color(0xFF6C63FF)), + const SizedBox(width: 10), + Text( + 'App Lock', + style: GoogleFonts.outfit( + color: Colors.white, + fontWeight: FontWeight.bold, + fontSize: 20, + ), + ), + ], + ), + actions: [ + Padding( + padding: const EdgeInsets.only(right: 16), + child: Chip( + backgroundColor: const Color(0xFF6C63FF).withValues(alpha: 0.2), + side: const BorderSide(color: Color(0xFF6C63FF)), + label: Text( + '${_lockedPackages.length} locked', + style: GoogleFonts.outfit( + color: const Color(0xFF6C63FF), + fontSize: 12, + ), + ), + ), + ), + ], + ), + body: _loading + ? const Center(child: CircularProgressIndicator(color: Color(0xFF6C63FF))) + : Column( + children: [ + if (!_isAccessibilityEnabled) _buildA11yBanner(), + Expanded( + child: _installedApps.isEmpty + ? Center( + child: Text( + 'No apps found', + style: GoogleFonts.outfit(color: Colors.white54), + ), + ) + : ListView.builder( + padding: const EdgeInsets.symmetric(vertical: 8), + itemCount: _installedApps.length, + itemBuilder: (ctx, i) => _buildAppTile(_installedApps[i]), + ), + ), + ], + ), + ); + } + + Widget _buildA11yBanner() { + return Container( + width: double.infinity, + margin: const EdgeInsets.all(12), + padding: const EdgeInsets.all(16), + decoration: BoxDecoration( + color: Colors.orange.withValues(alpha: 0.1), + borderRadius: BorderRadius.circular(12), + border: Border.all(color: Colors.orange.withValues(alpha: 0.5)), + ), + child: Column( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + Row(children: [ + const Icon(Icons.warning_amber_rounded, color: Colors.orange, size: 18), + const SizedBox(width: 8), + Text( + 'Accessibility Service Required', + style: GoogleFonts.outfit( + color: Colors.orange, fontWeight: FontWeight.bold), + ), + ]), + const SizedBox(height: 8), + Text( + 'App Lock needs Accessibility permission to block apps.', + style: GoogleFonts.outfit(color: Colors.white70, fontSize: 13), + ), + const SizedBox(height: 10), + TextButton( + onPressed: _openAccessibilitySettings, + style: TextButton.styleFrom( + backgroundColor: Colors.orange.withValues(alpha: 0.2), + padding: const EdgeInsets.symmetric(horizontal: 16, vertical: 8), + shape: RoundedRectangleBorder( + borderRadius: BorderRadius.circular(8)), + ), + child: Text( + 'Open Accessibility Settings', + style: GoogleFonts.outfit(color: Colors.orange, fontSize: 13), + ), + ), + ], + ), + ); + } + + Widget _buildAppTile(InstalledApp app) { + final isLocked = _lockedPackages.contains(app.packageName); + final attempts = _attemptCounts[app.packageName] ?? 0; + + return ListTile( + contentPadding: + const EdgeInsets.symmetric(horizontal: 20, vertical: 4), + leading: Container( + width: 44, + height: 44, + decoration: BoxDecoration( + color: const Color(0xFF1A1A2E), + borderRadius: BorderRadius.circular(10), + ), + child: Icon( + Icons.android_rounded, + color: isLocked ? const Color(0xFF6C63FF) : Colors.white38, + size: 24, + ), + ), + title: Text( + app.appName, + style: GoogleFonts.outfit( + color: Colors.white, + fontWeight: FontWeight.w500, + fontSize: 15, + ), + ), + subtitle: attempts > 0 + ? Text( + '$attempts blocked attempt${attempts == 1 ? '' : 's'} today', + style: GoogleFonts.outfit( + color: Colors.redAccent.withValues(alpha: 0.8), + fontSize: 12, + ), + ) + : null, + trailing: Switch( + value: isLocked, + activeColor: const Color(0xFF6C63FF), + onChanged: (val) => _toggleLock(app, val), + ), + ); + } +} diff --git a/lib/screens/dashboard/home_dashboard.dart b/lib/screens/dashboard/home_dashboard.dart new file mode 100644 index 0000000000000000000000000000000000000000..93bbb066863446fe93b0eb1857061fbc50467188 --- /dev/null +++ b/lib/screens/dashboard/home_dashboard.dart @@ -0,0 +1,90 @@ +import 'package:flutter/material.dart'; +import '../../theme/finanjo_theme.dart'; +import 'package:flutter_animate/flutter_animate.dart'; + +class HomeDashboard extends StatelessWidget { + const HomeDashboard({Key? key}) : super(key: key); + + @override + Widget build(BuildContext context) { + return Scaffold( + body: Container( + decoration: const BoxDecoration( + gradient: FinanjoTheme.premiumGradient, + ), + child: SafeArea( + child: Column( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + const SizedBox(height: 20), + Padding( + padding: const EdgeInsets.symmetric(horizontal: 24.0), + child: Row( + mainAxisAlignment: MainAxisAlignment.spaceBetween, + children: [ + Column( + crossAxisAlignment: CrossAxisAlignment.start, + children: const [ + Text('Welcome Back!', style: FinanjoTheme.headingStyle), + SizedBox(height: 4), + Text('Your security is active.', style: FinanjoTheme.subHeadingStyle), + ], + ).animate().fadeIn(duration: 600.ms).slideX(begin: -0.1, end: 0, curve: Curves.easeOutQuad), + const CircleAvatar( + radius: 24, + backgroundColor: FinanjoTheme.primaryPurple, + child: Icon(Icons.person, color: Colors.white), + ).animate().scale(delay: 200.ms, duration: 500.ms, curve: Curves.easeOutBack), + ], + ), + ), + const SizedBox(height: 40), + Center( + child: Container( + width: MediaQuery.of(context).size.width * 0.85, + padding: const EdgeInsets.all(32), + decoration: FinanjoTheme.cardDecoration, + child: Column( + children: [ + Container( + padding: const EdgeInsets.all(16), + decoration: BoxDecoration( + color: FinanjoTheme.successGreen.withOpacity(0.1), + shape: BoxShape.circle, + ), + child: const Icon(Icons.check_circle, size: 64, color: FinanjoTheme.successGreen), + ).animate(onPlay: (controller) => controller.repeat(reverse: true)) + .scale(begin: const Offset(1, 1), end: const Offset(1.05, 1.05), duration: 2.seconds), + const SizedBox(height: 24), + Text('Protection\nActive', textAlign: TextAlign.center, style: FinanjoTheme.headingStyle.copyWith(fontSize: 28)), + const SizedBox(height: 16), + const Text( + 'Your local AI is running. All your messages and keystrokes are analyzed securely on-device.', + textAlign: TextAlign.center, + style: FinanjoTheme.bodyStyle, + ), + ], + ), + ).animate().fadeIn(delay: 300.ms, duration: 800.ms).slideY(begin: 0.1, end: 0, curve: Curves.easeOutCubic), + ), + const Spacer(), + Center( + child: Padding( + padding: const EdgeInsets.all(24.0), + child: Row( + mainAxisAlignment: MainAxisAlignment.center, + children: [ + const Icon(Icons.lock, color: FinanjoTheme.textGrey, size: 16), + const SizedBox(width: 8), + Text('No data leaves your device', style: FinanjoTheme.subHeadingStyle.copyWith(fontSize: 14)), + ], + ), + ).animate().fadeIn(delay: 600.ms, duration: 800.ms), + ), + ], + ), + ), + ), + ); + } +} diff --git a/lib/screens/data_shield_screen.dart b/lib/screens/data_shield_screen.dart new file mode 100644 index 0000000000000000000000000000000000000000..9a858bd73bbec940aad29a69ee49828a1f179ea8 --- /dev/null +++ b/lib/screens/data_shield_screen.dart @@ -0,0 +1,588 @@ +import 'dart:async'; +import 'package:flutter/material.dart'; +import 'package:flutter/services.dart'; +import 'package:intl/intl.dart'; +import '../services/vector_service.dart'; +import '../services/storage_service.dart'; +import '../services/telemetry_service.dart'; +import 'app_lock_screen.dart'; +import 'vpn_shield_screen.dart'; + +class DataShieldScreen extends StatefulWidget { + const DataShieldScreen({super.key}); + + @override + State createState() => _DataShieldScreenState(); +} + +class _DataShieldScreenState extends State { + int _embeddingCount = 0; + + List stories = []; + List dataUsage = []; + List activeSensors = []; + bool isLoading = true; + bool hasPermission = false; + String selectedLanguage = 'english'; // english or hindi + DateTime lastScan = DateTime.now(); + + Timer? _sensorTimer; + + @override + void initState() { + super.initState(); + _loadEmbeddingCount(); + _fetchTelemetry(); + _sensorTimer = Timer.periodic(const Duration(seconds: 60), (_) { + _fetchActiveSensors(); + }); + } + + @override + void dispose() { + _sensorTimer?.cancel(); + super.dispose(); + } + + Future _loadEmbeddingCount() async { + if (!VectorService.isReady) return; + final db = await StorageService().database; + final count = await VectorService().embeddingCount(db); + if (mounted) setState(() => _embeddingCount = count); + } + + Future _fetchTelemetry() async { + if (!mounted) return; + setState(() => isLoading = true); + + final perm = await TelemetryService.hasUsagePermission(); + final st = await TelemetryService.getPrivacyStories(); + final dUsage = await TelemetryService.getDataUsage(); + final sensors = await TelemetryService.getActiveSensors(); + + if (mounted) { + setState(() { + hasPermission = perm; + stories = st; + dataUsage = dUsage; + activeSensors = sensors; + lastScan = DateTime.now(); + isLoading = false; + }); + } + } + + Future _fetchActiveSensors() async { + final sensors = await TelemetryService.getActiveSensors(); + if (mounted) { + setState(() { + activeSensors = sensors; + }); + } + } + + @override + Widget build(BuildContext context) { + return Scaffold( + backgroundColor: const Color(0xFF0F1117), + appBar: AppBar( + title: const Text( + 'Data Shield', + style: TextStyle(fontWeight: FontWeight.bold, color: Colors.white), + ), + backgroundColor: const Color(0xFF1A1D27), + foregroundColor: Colors.white, + elevation: 0, + actions: [ + // Language Toggle + Padding( + padding: const EdgeInsets.symmetric(vertical: 10, horizontal: 8), + child: Container( + decoration: BoxDecoration( + color: const Color(0xFF2D3145), + borderRadius: BorderRadius.circular(20), + ), + child: Row( + children: [ + _langButton('EN', 'english'), + _langButton('हिं', 'hindi'), + ], + ), + ), + ), + IconButton( + icon: const Icon(Icons.refresh, color: Colors.white70), + tooltip: 'Refresh', + onPressed: () { + _fetchTelemetry(); + }, + ), + IconButton( + icon: const Icon(Icons.shield, color: Colors.white70), + tooltip: 'DNS Shield', + onPressed: () => Navigator.push( + context, + MaterialPageRoute(builder: (_) => const VpnShieldScreen()), + ), + ), + IconButton( + icon: const Icon(Icons.lock_outline, color: Colors.white70), + tooltip: 'App Lock', + onPressed: () => Navigator.push( + context, + MaterialPageRoute(builder: (_) => const AppLockScreen()), + ), + ), + ], + ), + floatingActionButton: FloatingActionButton.extended( + onPressed: isLoading ? null : _fetchTelemetry, + backgroundColor: Colors.blueAccent, + icon: isLoading + ? const SizedBox(width: 20, height: 20, child: CircularProgressIndicator(color: Colors.white, strokeWidth: 2)) + : const Icon(Icons.search, color: Colors.white), + label: const Text('Scan Now', style: TextStyle(color: Colors.white, fontWeight: FontWeight.bold)), + ), + body: SingleChildScrollView( + padding: const EdgeInsets.all(16.0), + child: Column( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + if (!hasPermission && !isLoading) _buildPermissionBanner(), + const SizedBox(height: 16), + _buildLiveSensorStatus(), + const SizedBox(height: 24), + _sectionHeader('📊 Privacy Stories'), + const SizedBox(height: 8), + if (isLoading && stories.isEmpty) + const Center(child: Padding(padding: EdgeInsets.all(20), child: CircularProgressIndicator())) + else + ...stories.map(_buildStoryCard).toList(), + const SizedBox(height: 24), + if (dataUsage.isNotEmpty) ...[ + _sectionHeader('📤 Data Sent (last 24h)'), + const SizedBox(height: 8), + _buildDataUsageSection(), + const SizedBox(height: 24), + ], + _sectionHeader('🛡️ System Status'), + const SizedBox(height: 8), + _buildSystemStatusCard(), + const SizedBox(height: 80), // Fab spacing + ], + ), + ), + ); + } + + Widget _langButton(String label, String langVal) { + final active = selectedLanguage == langVal; + return GestureDetector( + onTap: () => setState(() => selectedLanguage = langVal), + child: Container( + padding: const EdgeInsets.symmetric(horizontal: 12, vertical: 4), + decoration: BoxDecoration( + color: active ? Colors.blueAccent : Colors.transparent, + borderRadius: BorderRadius.circular(20), + ), + child: Text( + label, + style: TextStyle( + color: active ? Colors.white : Colors.white54, + fontWeight: active ? FontWeight.bold : FontWeight.normal, + fontSize: 13, + ), + ), + ), + ); + } + + Widget _buildPermissionBanner() { + return Container( + padding: const EdgeInsets.all(16), + decoration: BoxDecoration( + color: Colors.amber.shade900.withValues(alpha: 0.2), + borderRadius: BorderRadius.circular(12), + border: Border.all(color: Colors.amber.shade700), + ), + child: Column( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + Row( + children: [ + Icon(Icons.warning_amber_rounded, color: Colors.amber.shade300), + const SizedBox(width: 8), + const Expanded( + child: Text( + 'Grant Usage Access for full insights', + style: TextStyle(color: Colors.white, fontWeight: FontWeight.bold, fontSize: 16), + ), + ), + ], + ), + const SizedBox(height: 8), + const Text( + 'Premithius reads app usage locally. Nothing leaves your device.', + style: TextStyle(color: Colors.white70, fontSize: 13), + ), + const SizedBox(height: 12), + ElevatedButton( + onPressed: () async { + const platform = MethodChannel('flutter/platform_channel'); + try { + await platform.invokeMethod('openSettingsIntent', 'android.settings.USAGE_ACCESS_SETTINGS'); + } catch (_) {} + }, + style: ElevatedButton.styleFrom( + backgroundColor: Colors.amber.shade700, + foregroundColor: Colors.white, + ), + child: const Text('Open Settings'), + ), + ], + ), + ); + } + + Widget _buildLiveSensorStatus() { + final activeMic = activeSensors.where((s) => s.sensor == 'microphone').toList(); + final activeCam = activeSensors.where((s) => s.sensor == 'camera').toList(); + + return Row( + children: [ + Expanded(child: _buildSensorCard('Microphone', Icons.mic, activeMic)), + const SizedBox(width: 12), + Expanded(child: _buildSensorCard('Camera', Icons.videocam, activeCam)), + ], + ); + } + + Widget _buildSensorCard(String title, IconData icon, List activeList) { + final bool isActive = activeList.isNotEmpty; + final Color bgColor = isActive ? Colors.red.shade900 : Colors.green.shade900.withValues(alpha: 0.5); + final Color borderColor = isActive ? Colors.red.shade400 : Colors.green.shade700; + + return Container( + padding: const EdgeInsets.all(12), + decoration: BoxDecoration( + color: bgColor, + borderRadius: BorderRadius.circular(12), + border: Border.all(color: borderColor, width: 2), + ), + child: Column( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + Row( + children: [ + Icon(icon, color: Colors.white, size: 20), + const SizedBox(width: 8), + Text(title, style: const TextStyle(color: Colors.white, fontWeight: FontWeight.bold)), + if (isActive) ...[ + const Spacer(), + Container( + width: 8, height: 8, + decoration: const BoxDecoration( + color: Colors.white, + shape: BoxShape.circle, + ), + ), + ] + ], + ), + const SizedBox(height: 8), + Text( + isActive ? "LIVE — ${activeList.first.appName}" : "No apps listening", + style: const TextStyle(color: Colors.white70, fontSize: 13), + maxLines: 1, overflow: TextOverflow.ellipsis, + ) + ], + ), + ); + } + + Widget _buildStoryCard(PrivacyStory story) { + Color badgeColor; + switch(story.severity) { + case 'CRITICAL': badgeColor = Colors.red; break; + case 'HIGH': badgeColor = Colors.orange; break; + case 'MEDIUM': badgeColor = Colors.amber; break; + case 'SAFE': badgeColor = Colors.green; break; + default: badgeColor = Colors.grey; + } + + final text = selectedLanguage == 'hindi' ? story.hindi : story.english; + + return Container( + margin: const EdgeInsets.only(bottom: 12), + padding: const EdgeInsets.all(16), + decoration: BoxDecoration( + color: const Color(0xFF1A1D27), + borderRadius: BorderRadius.circular(12), + border: Border.all(color: const Color(0xFF2D3145)), + boxShadow: [ + BoxShadow( + color: Colors.black.withValues(alpha: 0.2), + blurRadius: 8, + offset: const Offset(0, 4), + ), + ], + ), + child: Row( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + Text(story.emoji, style: const TextStyle(fontSize: 32)), + const SizedBox(width: 16), + Expanded( + child: Column( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + Container( + padding: const EdgeInsets.symmetric(horizontal: 6, vertical: 2), + decoration: BoxDecoration( + color: badgeColor.withValues(alpha: 0.2), + borderRadius: BorderRadius.circular(4), + border: Border.all(color: badgeColor), + ), + child: Text(story.severity, style: TextStyle(color: badgeColor, fontSize: 10, fontWeight: FontWeight.bold)), + ), + const SizedBox(height: 8), + Text( + text, + style: const TextStyle( + color: Colors.white, + height: 1.4, + fontSize: 14, + ), + ), + if (story.packageName.isNotEmpty && story.severity != 'SAFE') ...[ + const SizedBox(height: 12), + SizedBox( + height: 32, + child: OutlinedButton( + style: OutlinedButton.styleFrom( + foregroundColor: Colors.white70, + side: const BorderSide(color: Colors.white24), + shape: RoundedRectangleBorder(borderRadius: BorderRadius.circular(8)), + ), + onPressed: () async { + const channel = MethodChannel('in.inmodel.premithius/accessibility'); + try { + await channel.invokeMethod('launchApp', {'packageName': story.packageName}); + } catch (_) {} + }, + child: const Text('Open App', style: TextStyle(fontSize: 12)), + ), + ) + ] + ], + ), + ), + ], + ), + ); + } + + Widget _buildDataUsageSection() { + return Container( + padding: const EdgeInsets.all(16), + decoration: BoxDecoration( + color: const Color(0xFF1A1D27), + borderRadius: BorderRadius.circular(12), + border: Border.all(color: const Color(0xFF2D3145)), + ), + child: Column( + children: dataUsage.take(5).map((usage) { + final maxMb = dataUsage.first.mbSent; + final pct = maxMb > 0 ? (usage.mbSent / maxMb) : 0.0; + return Padding( + padding: const EdgeInsets.only(bottom: 12.0), + child: Column( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + Row( + mainAxisAlignment: MainAxisAlignment.spaceBetween, + children: [ + Text(usage.appName, style: const TextStyle(color: Colors.white, fontSize: 13, fontWeight: FontWeight.bold)), + Text("${usage.mbSent.toStringAsFixed(1)} MB", style: const TextStyle(color: Colors.white70, fontSize: 12)), + ], + ), + const SizedBox(height: 6), + LinearProgressIndicator( + value: pct, + backgroundColor: const Color(0xFF2D3145), + color: usage.mbSent > 100 ? Colors.redAccent : Colors.blueAccent, + minHeight: 6, + borderRadius: BorderRadius.circular(4), + ), + ], + ), + ); + }).toList(), + ), + ); + } + + Widget _sectionHeader(String title) { + return Text( + title, + style: const TextStyle( + color: Colors.white, + fontSize: 18, + fontWeight: FontWeight.bold, + letterSpacing: 0.3, + ), + ); + } + + Widget _buildSystemStatusCard() { + final bool vecReady = VectorService.isReady; + final String vecVersion = VectorService.vecVersion; + + return Container( + padding: const EdgeInsets.all(16), + decoration: BoxDecoration( + color: const Color(0xFF1A1D27), + borderRadius: BorderRadius.circular(16), + border: Border.all( + color: const Color(0xFF2D3145), + width: 1, + ), + boxShadow: [ + BoxShadow( + color: Colors.black.withValues(alpha: 0.3), + blurRadius: 12, + offset: const Offset(0, 4), + ), + ], + ), + child: Column( + children: [ + _statusRow( + 'Layer 1 — India Threat Pack', + true, + 'ACTIVE', + ), + const Divider(color: Color(0xFF2D3145), height: 16), + _statusRow( + 'Layer 2 — Vector Search', + vecReady, + vecReady ? 'ACTIVE' : 'DISABLED', + ), + const Divider(color: Color(0xFF2D3145), height: 16), + _statusRow( + 'Layer 3 — Random Forest', + true, + 'ACTIVE', + ), + const Divider(color: Color(0xFF2D3145), height: 16), + _statusRow( + 'Layer 4 — MobileBERT', + true, + 'ACTIVE', + ), + const Divider(color: Color(0xFF2D3145), height: 16), + _infoRow( + Icons.extension, + 'sqlite-vec version', + vecReady ? vecVersion : 'not loaded', + vecReady ? Colors.blueAccent : Colors.grey, + ), + const Divider(color: Color(0xFF2D3145), height: 16), + _infoRow( + Icons.storage, + 'Embeddings in store', + vecReady ? '$_embeddingCount' : '—', + vecReady ? Colors.blueAccent : Colors.grey, + ), + const Divider(color: Color(0xFF2D3145), height: 16), + _infoRow( + Icons.bar_chart, + 'Usage Stats Permission', + hasPermission ? 'GRANTED' : 'NEEDED', + hasPermission ? Colors.green : Colors.amber, + ), + const Divider(color: Color(0xFF2D3145), height: 16), + _infoRow( + Icons.article, + 'Privacy Stories', + '${stories.length} generated', + Colors.blueAccent, + ), + const Divider(color: Color(0xFF2D3145), height: 16), + _infoRow( + Icons.schedule, + 'Last scan', + DateFormat('HH:mm:ss').format(lastScan), + Colors.white70, + ), + ], + ), + ); + } + + Widget _statusRow(String label, bool isActive, String statusText) { + final Color statusColor = + isActive ? const Color(0xFF00E676) : Colors.grey; + final Color pillBg = + isActive ? const Color(0xFF00E676).withValues(alpha: 0.15) : Colors.grey.withValues(alpha: 0.15); + + return Row( + mainAxisAlignment: MainAxisAlignment.spaceBetween, + children: [ + Expanded( + child: Text( + label, + style: const TextStyle( + color: Colors.white70, + fontSize: 14, + ), + ), + ), + Container( + padding: const EdgeInsets.symmetric(horizontal: 10, vertical: 4), + decoration: BoxDecoration( + color: pillBg, + borderRadius: BorderRadius.circular(20), + border: Border.all(color: statusColor.withValues(alpha: 0.5)), + ), + child: Text( + statusText, + style: TextStyle( + color: statusColor, + fontSize: 12, + fontWeight: FontWeight.bold, + letterSpacing: 0.5, + ), + ), + ), + ], + ); + } + + Widget _infoRow(IconData icon, String label, String value, Color valueColor) { + return Row( + mainAxisAlignment: MainAxisAlignment.spaceBetween, + children: [ + Row( + children: [ + Icon(icon, color: Colors.white54, size: 16), + const SizedBox(width: 8), + Text( + label, + style: const TextStyle(color: Colors.white70, fontSize: 14), + ), + ], + ), + Text( + value, + style: TextStyle( + color: valueColor, + fontSize: 14, + fontWeight: FontWeight.w600, + fontFamily: 'monospace', + ), + ), + ], + ); + } +} diff --git a/lib/screens/vpn_shield_screen.dart b/lib/screens/vpn_shield_screen.dart new file mode 100644 index 0000000000000000000000000000000000000000..d0f406be0501cecdcca6501e5a36a458b86af7e0 --- /dev/null +++ b/lib/screens/vpn_shield_screen.dart @@ -0,0 +1,319 @@ +import 'dart:async'; +import 'package:flutter/material.dart'; +import 'package:google_fonts/google_fonts.dart'; +import 'package:sqflite/sqflite.dart'; +import '../services/vpn_service.dart'; +import '../services/storage_service.dart'; + +class VpnShieldScreen extends StatefulWidget { + const VpnShieldScreen({super.key}); + + @override + State createState() => _VpnShieldScreenState(); +} + +class _VpnShieldScreenState extends State { + bool _isActive = false; + VpnStats? _stats; + int _totalDomains = 0; + final TextEditingController _domainController = TextEditingController(); + Timer? _pollingTimer; + + @override + void initState() { + super.initState(); + _checkStatus(); + _pollingTimer = Timer.periodic(const Duration(seconds: 2), (_) => _checkStatus()); + } + + @override + void dispose() { + _pollingTimer?.cancel(); + _domainController.dispose(); + super.dispose(); + } + + Future _checkStatus() async { + final active = KavachaVpn.isRunning; + final stats = await KavachaVpn.getStats(); + + final db = await StorageService().database; + final totalResult = await db.rawQuery('SELECT COUNT(*) as c FROM scam_domains'); + final total = totalResult.isNotEmpty ? totalResult.first['c'] as int : 0; + + if (mounted) { + setState(() { + _isActive = active; + _stats = stats; + _totalDomains = total; + }); + } + } + + Future _toggleVpn(bool value) async { + if (value) { + await KavachaVpn.start(); + } else { + await KavachaVpn.stop(); + } + _checkStatus(); + } + + Future _addDomainManually() async { + final domain = _domainController.text.trim().toLowerCase(); + if (domain.isEmpty) return; + + try { + final db = await StorageService().database; + await db.insert('scam_domains', { + 'domain': domain, + 'category': 'User Added', + 'source': 'user', + 'hit_count': 0, + 'created_at': DateTime.now().millisecondsSinceEpoch, + }, conflictAlgorithm: ConflictAlgorithm.ignore); + + _domainController.clear(); + await KavachaVpn.reloadBlocklist(); + _checkStatus(); + + if (mounted) { + ScaffoldMessenger.of(context).showSnackBar( + SnackBar(content: Text('Domain $domain added to blocklist')), + ); + } + } catch (e) { + if (mounted) { + ScaffoldMessenger.of(context).showSnackBar( + SnackBar(content: Text('Failed to add domain: $e')), + ); + } + } + } + + @override + Widget build(BuildContext context) { + return Scaffold( + backgroundColor: Colors.black, + appBar: AppBar( + title: Text('DNS Shield', style: GoogleFonts.outfit(fontWeight: FontWeight.bold, color: Colors.white)), + backgroundColor: Colors.transparent, + iconTheme: const IconThemeData(color: Colors.white), + ), + body: SingleChildScrollView( + padding: const EdgeInsets.all(24), + child: Column( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + _buildHeader(), + const SizedBox(height: 32), + _buildStatsGrid(), + const SizedBox(height: 32), + _buildTopBlocked(), + const SizedBox(height: 32), + _buildManagement(), + const SizedBox(height: 48), + _buildPrivacyNote(), + ], + ), + ), + ); + } + + Widget _buildHeader() { + return Container( + padding: const EdgeInsets.all(24), + decoration: BoxDecoration( + color: const Color(0xFF1E1E2C), + borderRadius: BorderRadius.circular(20), + border: Border.all(color: _isActive ? Colors.green.withOpacity(0.3) : Colors.white10), + ), + child: Column( + children: [ + Row( + mainAxisAlignment: MainAxisAlignment.spaceBetween, + children: [ + Text( + 'VPN Shield', + style: GoogleFonts.outfit(fontSize: 24, fontWeight: FontWeight.bold, color: Colors.white), + ), + Switch( + value: _isActive, + onChanged: _toggleVpn, + activeColor: Colors.greenAccent, + inactiveThumbColor: Colors.grey, + inactiveTrackColor: Colors.white24, + ), + ], + ), + const SizedBox(height: 16), + Container( + padding: const EdgeInsets.symmetric(horizontal: 16, vertical: 8), + decoration: BoxDecoration( + color: _isActive ? Colors.green.withOpacity(0.2) : Colors.grey.withOpacity(0.2), + borderRadius: BorderRadius.circular(20), + ), + child: Text( + _isActive ? 'Active — all DNS protected' : 'Disabled', + style: GoogleFonts.outfit( + color: _isActive ? Colors.greenAccent : Colors.grey, + fontWeight: FontWeight.bold, + ), + ), + ), + const SizedBox(height: 16), + Text( + 'Local only — no data sent to any server', + style: GoogleFonts.outfit(color: Colors.white54, fontSize: 14), + ), + ], + ), + ); + } + + Widget _buildStatsGrid() { + return GridView.count( + crossAxisCount: 2, + shrinkWrap: true, + physics: const NeverScrollableScrollPhysics(), + crossAxisSpacing: 16, + mainAxisSpacing: 16, + childAspectRatio: 1.5, + children: [ + _buildStatCard('Blocked today', '\${_stats?.blockedToday ?? 0}', Colors.orangeAccent), + _buildStatCard('Total domains', '$_totalDomains', Colors.blueAccent), + _buildStatCard('Last blocked', _stats?.lastBlockedDomain ?? 'none', Colors.redAccent, isDomain: true), + _buildStatCard('Status', _isActive ? 'Local TUN' : 'Off', _isActive ? Colors.greenAccent : Colors.grey), + ], + ); + } + + Widget _buildStatCard(String title, String value, Color color, {bool isDomain = false}) { + return Container( + padding: const EdgeInsets.all(16), + decoration: BoxDecoration( + color: const Color(0xFF1E1E2C), + borderRadius: BorderRadius.circular(16), + ), + child: Column( + crossAxisAlignment: CrossAxisAlignment.start, + mainAxisAlignment: MainAxisAlignment.center, + children: [ + Text(title, style: GoogleFonts.outfit(color: Colors.white54, fontSize: 13)), + const SizedBox(height: 8), + Text( + value, + style: GoogleFonts.outfit( + color: color, + fontSize: isDomain ? 14 : 24, + fontWeight: FontWeight.bold, + ), + maxLines: 1, + overflow: TextOverflow.ellipsis, + ), + ], + ), + ); + } + + Widget _buildTopBlocked() { + final domains = _stats?.topBlockedDomains ?? []; + return Column( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + Text('Top Blocked Domains', style: GoogleFonts.outfit(fontSize: 18, fontWeight: FontWeight.bold, color: Colors.white)), + const SizedBox(height: 16), + if (domains.isEmpty) + Text('No domains blocked yet.', style: GoogleFonts.outfit(color: Colors.white54)), + for (var domain in domains) + Container( + margin: const EdgeInsets.only(bottom: 12), + padding: const EdgeInsets.all(16), + decoration: BoxDecoration( + color: const Color(0xFF1E1E2C), + borderRadius: BorderRadius.circular(12), + ), + child: Row( + children: [ + const Icon(Icons.block, color: Colors.redAccent, size: 20), + const SizedBox(width: 12), + Expanded( + child: Text(domain.domain, style: GoogleFonts.outfit(color: Colors.white, fontSize: 16)), + ), + Container( + padding: const EdgeInsets.symmetric(horizontal: 12, vertical: 4), + decoration: BoxDecoration( + color: Colors.red.withOpacity(0.2), + borderRadius: BorderRadius.circular(12), + ), + child: Text('\${domain.hitCount}', style: GoogleFonts.outfit(color: Colors.redAccent, fontWeight: FontWeight.bold)), + ), + ], + ), + ), + ], + ); + } + + Widget _buildManagement() { + return Column( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + Text('Blocklist Management', style: GoogleFonts.outfit(fontSize: 18, fontWeight: FontWeight.bold, color: Colors.white)), + const SizedBox(height: 16), + Row( + children: [ + Expanded( + child: TextField( + controller: _domainController, + style: const TextStyle(color: Colors.white), + decoration: InputDecoration( + hintText: 'Add domain manually', + hintStyle: const TextStyle(color: Colors.white38), + filled: true, + fillColor: const Color(0xFF1E1E2C), + border: OutlineInputBorder(borderRadius: BorderRadius.circular(12), borderSide: BorderSide.none), + contentPadding: const EdgeInsets.symmetric(horizontal: 16, vertical: 14), + ), + ), + ), + const SizedBox(width: 12), + ElevatedButton( + onPressed: _addDomainManually, + style: ElevatedButton.styleFrom( + backgroundColor: const Color(0xFF6C63FF), + padding: const EdgeInsets.all(14), + shape: RoundedRectangleBorder(borderRadius: BorderRadius.circular(12)), + ), + child: const Icon(Icons.add, color: Colors.white), + ) + ], + ), + ], + ); + } + + Widget _buildPrivacyNote() { + return Container( + padding: const EdgeInsets.all(16), + decoration: BoxDecoration( + color: Colors.blue.withOpacity(0.1), + borderRadius: BorderRadius.circular(12), + border: Border.all(color: Colors.blue.withOpacity(0.3)), + ), + child: Row( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + const Icon(Icons.privacy_tip, color: Colors.blueAccent), + const SizedBox(width: 16), + Expanded( + child: Text( + 'Premithius VPN runs entirely on your device. DNS queries are checked locally and forwarded to Cloudflare 1.1.1.1 for safe domains only. Blocked domains return NXDOMAIN — no data reaches the scam site.', + style: GoogleFonts.outfit(color: Colors.white70, fontSize: 13, height: 1.5), + ), + ), + ], + ), + ); + } +} diff --git a/lib/services/accessibility_service.dart b/lib/services/accessibility_service.dart new file mode 100644 index 0000000000000000000000000000000000000000..fa3e2c1f0a08f067ae2cb19fad4828f4890a9fa1 --- /dev/null +++ b/lib/services/accessibility_service.dart @@ -0,0 +1,99 @@ +import 'package:flutter/services.dart'; +import 'package:flutter/widgets.dart'; +import 'app_lock_service.dart'; +import 'storage_service.dart'; +import '../kavacha/threat_pack/otp_context_verifier.dart'; + +/// Bridge between Flutter and PremithiusAccessibilityService (Kotlin). +/// Receives foreground app changes and biometric auth requests. +class AccessibilityBridge { + static const _channel = MethodChannel('in.inmodel.premithus/accessibility'); + static const _authChannel = MethodChannel('in.inmodel.premithus/auth'); + + // Current foreground app context — used by keyboard + OTP verifier + static String currentPackage = ''; + static String currentAppName = ''; + static String currentToneContext = 'neutral'; + + // Listeners (e.g. keyboard_layout subscribes to tone changes) + static final List _toneListeners = []; + + static void addToneListener(VoidCallback cb) => _toneListeners.add(cb); + static void removeToneListener(VoidCallback cb) => _toneListeners.remove(cb); + + static void initialize() { + // Listen for foreground app changes from Kotlin + _channel.setMethodCallHandler((call) async { + if (call.method == 'onForegroundChanged') { + final args = call.arguments as Map; + currentPackage = args['package'] as String? ?? ''; + currentAppName = args['appName'] as String? ?? ''; + currentToneContext = args['toneContext'] as String? ?? 'neutral'; + + // Notify tone listeners (keyboard shortcut bar) + for (final cb in _toneListeners) { + cb(); + } + + // Check OTP context — is foreground app matching recent OTP? + OtpContextVerifier.checkContext(currentPackage); + } + }); + + // Listen for biometric auth requests from OverlayService (via Kotlin) + _authChannel.setMethodCallHandler((call) async { + if (call.method == 'requestBiometricAuth') { + final args = call.arguments as Map; + final packageName = args['packageName'] as String; + final appName = args['appName'] as String; + + final authenticated = await _authenticate(appName); + + if (authenticated) { + // Temporarily unlock — launch the app + await AppLockService.temporarilyUnlock(packageName); + _launchApp(packageName); + } + + // Log attempt + await StorageService().logAccessAttempt( + packageName: packageName, + wasAllowed: authenticated, + appName: appName, + ); + } + }); + } + + static Future _authenticate(String appName) async { + // Use local_auth if available; keep graceful fallback + try { + const localAuth = MethodChannel('plugins.flutter.io/local_auth'); + final result = await localAuth.invokeMethod( + 'authenticate', + { + 'localizedReason': 'Authenticate to open $appName', + 'useErrorDialogs': true, + 'stickyAuth': true, + }, + ); + return result ?? false; + } catch (_) { + return false; + } + } + + /// Returns true if PremithiusAccessibilityService is enabled. + static Future isServiceEnabled() async { + try { + final result = await _channel.invokeMethod('isServiceEnabled'); + return result ?? false; + } catch (_) { + return false; + } + } + + static void _launchApp(String packageName) { + _channel.invokeMethod('launchApp', {'packageName': packageName}); + } +} diff --git a/lib/services/app_lock_service.dart b/lib/services/app_lock_service.dart new file mode 100644 index 0000000000000000000000000000000000000000..2452608014de0cbe7c47d64aaefa340c7542ae54 --- /dev/null +++ b/lib/services/app_lock_service.dart @@ -0,0 +1,92 @@ +import 'package:flutter/services.dart'; +import 'storage_service.dart'; +import 'accessibility_service.dart'; + +/// Manages locked apps in the locked_apps SQLite table. +class AppLockService { + static const _appsChannel = MethodChannel('in.inmodel.premithus/apps'); + + /// Lock an app — adds to locked_apps table. + static Future lockApp(String packageName, String appName) async { + await StorageService().insertLockedApp( + packageName: packageName, + appName: appName, + authMethod: 'biometric', + ); + } + + /// Permanently unlock an app — removes from locked_apps table. + static Future unlockApp(String packageName) async { + await StorageService().removeLockedApp(packageName); + } + + /// Temporarily allow one launch (10-second window). + /// AccessibilityService will see temporary_unlock_until in the future and skip lock. + static Future temporarilyUnlock(String packageName) async { + await StorageService().setTemporaryUnlock( + packageName, + expires: DateTime.now().add(const Duration(seconds: 10)), + ); + } + + /// Get all currently locked apps. + static Future> getLockedApps() async { + final rows = await StorageService().getLockedApps(); + return rows.map(LockedApp.fromMap).toList(); + } + + /// Check if a specific app is locked. + static Future isLocked(String packageName) async { + return StorageService().isAppLocked(packageName); + } + + /// Get installed apps via Kotlin MethodChannel. + /// Filters to user-installed + system apps with launcher icons. + static Future> getInstalledApps() async { + final List result = await _appsChannel.invokeMethod('getInstalledApps'); + return result + .map((e) => InstalledApp.fromMap(Map.from(e as Map))) + .toList(); + } +} + +class LockedApp { + final String packageName; + final String appName; + final String authMethod; + final DateTime lockedAt; + final int accessAttempts; + + const LockedApp({ + required this.packageName, + required this.appName, + required this.authMethod, + required this.lockedAt, + required this.accessAttempts, + }); + + factory LockedApp.fromMap(Map map) { + return LockedApp( + packageName: map['package_name'] as String, + appName: map['app_name'] as String, + authMethod: map['auth_method'] as String? ?? 'biometric', + lockedAt: DateTime.fromMillisecondsSinceEpoch( + map['locked_at'] as int? ?? 0), + accessAttempts: map['access_attempts'] as int? ?? 0, + ); + } +} + +class InstalledApp { + final String packageName; + final String appName; + + const InstalledApp({required this.packageName, required this.appName}); + + factory InstalledApp.fromMap(Map map) { + return InstalledApp( + packageName: map['packageName'] as String, + appName: map['appName'] as String, + ); + } +} diff --git a/lib/services/grammar_service.dart b/lib/services/grammar_service.dart new file mode 100644 index 0000000000000000000000000000000000000000..899ddc84fa6d35f8d81ec843c77c9f921ae5ee50 --- /dev/null +++ b/lib/services/grammar_service.dart @@ -0,0 +1,33 @@ +import 'dart:async'; + +class GrammarService { + static final GrammarService _instance = GrammarService._internal(); + factory GrammarService() => _instance; + GrammarService._internal(); + + bool _isLoaded = false; + + Future init() async { + // In a real implementation using languagetool_textfield: + // await LanguageToolOffline.init(); + _isLoaded = true; + print("LanguageTool offline grammar service initialized."); + } + + Future fixGrammar(String text) async { + if (!_isLoaded) return text; + + // Simulate the <50ms inference time of LanguageTool offline + await Future.delayed(const Duration(milliseconds: 30)); + + String corrected = text; + + // Mock corrections for the demonstration + corrected = corrected.replaceAll(RegExp(r'\bi goes\b', caseSensitive: false), 'I go'); + corrected = corrected.replaceAll(RegExp(r'\bhe go\b', caseSensitive: false), 'he goes'); + corrected = corrected.replaceAll(RegExp(r'\ba apple\b', caseSensitive: false), 'an apple'); + corrected = corrected.replaceAll(RegExp(r'\btheir is\b', caseSensitive: false), 'there is'); + + return corrected; + } +} diff --git a/lib/services/llm_service.dart b/lib/services/llm_service.dart new file mode 100644 index 0000000000000000000000000000000000000000..6b64040abcb444e00bc4e3e5733ad30b99377fed --- /dev/null +++ b/lib/services/llm_service.dart @@ -0,0 +1,28 @@ +import 'dart:async'; + +class LlmService { + static final LlmService _instance = LlmService._internal(); + factory LlmService() => _instance; + LlmService._internal(); + + bool _isInit = false; + + Future processAction(String text, String action) async { + // LLM feature is disabled in V0.0.2 to save battery and RAM + // Return mock grammar responses or null + await Future.delayed(const Duration(milliseconds: 500)); + + if (action == 'Formal') { + return 'Rewrite the following text formally: $text'; + } else if (action == 'Casual') { + return 'Rewrite the following text casually: $text'; + } else if (action == 'Short') { + return 'Make the following text much shorter: $text'; + } else if (action == 'Sum') { + return 'Summarize the following text: $text'; + } + + return 'Error: LLM engine is offline in V0.0.2'; + } +} + diff --git a/lib/services/scam_service.dart b/lib/services/scam_service.dart new file mode 100644 index 0000000000000000000000000000000000000000..18694bb0924e0263621594a32620ca359f0a73e3 --- /dev/null +++ b/lib/services/scam_service.dart @@ -0,0 +1,90 @@ +import 'package:sqflite/sqflite.dart'; +import 'storage_service.dart'; +import '../kavacha/kavacha_pipeline.dart'; +import '../kavacha/models/kavacha_models.dart'; + +// Represents the result of a scan +class ScamResult { + final bool isScam; + final double confidence; + final String category; + final String threatLevel; + final int triggeredLayer; + final String layerLabel; + + ScamResult({ + required this.isScam, + required this.confidence, + required this.category, + required this.threatLevel, + this.triggeredLayer = 0, + this.layerLabel = '', + }); +} + +class ScamService { + static final ScamService _instance = ScamService._internal(); + factory ScamService() => _instance; + ScamService._internal(); + + final StorageService _storage = StorageService(); + final KavachaPipeline _pipeline = KavachaPipeline(); + + bool _isInit = false; + + Future init() async { + if (_isInit) return; + try { + await _pipeline.init(); + _isInit = true; + } catch (_) { + // Handle initialization error + } + } + + Future analyzeSms(String sender, String message) async { + // Pipeline does the heavily lifting including whitelist, vector searches, etc. + final result = await _pipeline.analyze(sender, message); + final scamResult = result.verdict == Verdict.block ? result.asThreat() : result.asSafe(); + + if (scamResult.isScam) { + // 3. Log to SQLite + try { + await _storage.insertScamLog({ + 'sender': sender, + 'message_preview': message.length > 100 ? message.substring(0, 100) : message, + 'category': scamResult.category, + 'confidence': scamResult.confidence, + 'threat_level': scamResult.threatLevel, + 'user_feedback': 'pending', + 'created_at': DateTime.now().millisecondsSinceEpoch, + }); + } catch (e) { + // Log error silently or use a logger + } + } + + return scamResult; + } + + Future processFeedback(String sender, String message, bool isScam) async { + try { + final Database db = await _storage.database; + if (isScam) { + await db.insert('scam_patterns', { + 'pattern': message.length > 50 ? message.substring(0, 50) : message, + 'category': 'User Confirmed', + 'user_confirmed': 1, + 'created_at': DateTime.now().millisecondsSinceEpoch, + }); + } else { + await db.insert('whitelist', { + 'sender': sender, + 'created_at': DateTime.now().millisecondsSinceEpoch, + }); + } + } catch (e) { + print('Feedback write error: \$e'); + } + } +} diff --git a/lib/services/storage_service.dart b/lib/services/storage_service.dart new file mode 100644 index 0000000000000000000000000000000000000000..6ad1d01dc0ad8e431a649a7a137141fb41b212e8 --- /dev/null +++ b/lib/services/storage_service.dart @@ -0,0 +1,320 @@ +import 'dart:convert'; +import 'package:flutter/services.dart'; +import 'package:sqflite/sqflite.dart'; +import 'package:path/path.dart'; + +class StorageService { + static final StorageService _instance = StorageService._internal(); + factory StorageService() => _instance; + StorageService._internal(); + + Database? _database; + + Future get database async { + if (_database != null) return _database!; + _database = await _initDB(); + return _database!; + } + + Future _initDB() async { + String path = join(await getDatabasesPath(), 'premithius.db'); + return await openDatabase( + path, + version: 3, + onCreate: _createTables, + onUpgrade: _onUpgrade, + ); + } + + Future _createTables(Database db, int version) async { + await db.execute(''' + CREATE TABLE keyboard_history ( + id INTEGER PRIMARY KEY AUTOINCREMENT, + app_context TEXT, + original_text TEXT, + action TEXT, + result_text TEXT, + accepted INTEGER DEFAULT 0, + created_at INTEGER + ) + '''); + + await db.execute(''' + CREATE TABLE scam_log ( + id INTEGER PRIMARY KEY AUTOINCREMENT, + sender TEXT, + message_preview TEXT, + category TEXT, + confidence REAL, + threat_level TEXT, + user_feedback TEXT, + created_at INTEGER + ) + '''); + + await db.execute(''' + CREATE TABLE scam_patterns ( + id INTEGER PRIMARY KEY AUTOINCREMENT, + pattern TEXT NOT NULL, + category TEXT, + hit_count INTEGER DEFAULT 1, + user_confirmed INTEGER DEFAULT 0, + created_at INTEGER + ) + '''); + + await db.execute(''' + CREATE TABLE whitelist ( + id INTEGER PRIMARY KEY AUTOINCREMENT, + sender TEXT UNIQUE, + created_at INTEGER + ) + '''); + + await db.execute(''' + CREATE TABLE upi_events ( + id INTEGER PRIMARY KEY AUTOINCREMENT, + vpa TEXT, + amount REAL, + fraud_type TEXT, + confidence REAL, + created_at INTEGER + ) + '''); + + await db.execute(''' + CREATE TABLE shield_warnings ( + id INTEGER PRIMARY KEY AUTOINCREMENT, + warning_type TEXT, + app_context TEXT, + user_action TEXT, + created_at INTEGER + ) + '''); + + await db.execute(''' + CREATE TABLE permission_anomalies ( + id INTEGER PRIMARY KEY AUTOINCREMENT, + app_package TEXT, + permission TEXT, + access_count INTEGER, + time_window TEXT, + severity TEXT, + created_at INTEGER + ) + '''); + + await db.execute(''' + CREATE TABLE festival_calendar ( + id INTEGER PRIMARY KEY, + name TEXT, + start_date TEXT, + end_date TEXT, + sensitivity_multiplier REAL + ) + '''); + + await _createAppLockTables(db); + await _createVpnTables(db); + await _seedScamDomains(db); + } + + Future _onUpgrade(Database db, int oldVersion, int newVersion) async { + if (oldVersion < 2) { + await _createAppLockTables(db); + } + if (oldVersion < 3) { + await _createVpnTables(db); + await _seedScamDomains(db); + } + } + + Future _createAppLockTables(Database db) async { + await db.execute(''' + CREATE TABLE IF NOT EXISTS locked_apps ( + id INTEGER PRIMARY KEY AUTOINCREMENT, + package_name TEXT UNIQUE NOT NULL, + app_name TEXT NOT NULL, + auth_method TEXT DEFAULT 'biometric', + locked_at INTEGER NOT NULL, + access_attempts INTEGER DEFAULT 0, + temporary_unlock_until INTEGER DEFAULT 0 + ) + '''); + + await db.execute(''' + CREATE TABLE IF NOT EXISTS access_log ( + id INTEGER PRIMARY KEY AUTOINCREMENT, + package_name TEXT NOT NULL, + app_name TEXT, + was_allowed INTEGER DEFAULT 0, + attempted_at INTEGER NOT NULL + ) + '''); + } + + // --- Helpers for Scam Logging --- + Future insertScamLog(Map row) async { + Database db = await database; + return await db.insert('scam_log', row); + } + + Future>> getScamLogs() async { + Database db = await database; + return await db.query('scam_log', orderBy: 'created_at DESC'); + } + + // --- Helpers for Pattern Learning --- + Future insertKeyboardLog(Map row) async { + Database db = await database; + return await db.insert('keyboard_history', row); + } + + Future?> checkLocalPattern(String text) async { + Database db = await database; + // VERY simplified exact phrase matching for hackathon scale. + // Real implementation would do tokenized LIKE matching. + final List> maps = await db.query('scam_patterns'); + for (var row in maps) { + if (text.toLowerCase().contains((row['pattern'] as String).toLowerCase())) { + return row; + } + } + return null; + } + + // --- App Lock Helpers --- + Future insertLockedApp({ + required String packageName, + required String appName, + String authMethod = 'biometric', + }) async { + final db = await database; + await db.insert( + 'locked_apps', + { + 'package_name': packageName, + 'app_name': appName, + 'auth_method': authMethod, + 'locked_at': DateTime.now().millisecondsSinceEpoch, + 'access_attempts': 0, + 'temporary_unlock_until': 0, + }, + conflictAlgorithm: ConflictAlgorithm.replace, + ); + } + + Future removeLockedApp(String packageName) async { + final db = await database; + await db.delete('locked_apps', where: 'package_name = ?', whereArgs: [packageName]); + } + + Future>> getLockedApps() async { + final db = await database; + return db.query('locked_apps', orderBy: 'locked_at DESC'); + } + + Future isAppLocked(String packageName) async { + final db = await database; + final rows = await db.query( + 'locked_apps', + where: 'package_name = ?', + whereArgs: [packageName], + ); + if (rows.isEmpty) return false; + final tempUntil = rows.first['temporary_unlock_until'] as int? ?? 0; + return tempUntil == 0 || DateTime.now().millisecondsSinceEpoch > tempUntil; + } + + Future setTemporaryUnlock(String packageName, {required DateTime expires}) async { + final db = await database; + await db.update( + 'locked_apps', + {'temporary_unlock_until': expires.millisecondsSinceEpoch}, + where: 'package_name = ?', + whereArgs: [packageName], + ); + } + + Future logAccessAttempt({ + required String packageName, + required bool wasAllowed, + String? appName, + }) async { + final db = await database; + await db.insert('access_log', { + 'package_name': packageName, + 'app_name': appName, + 'was_allowed': wasAllowed ? 1 : 0, + 'attempted_at': DateTime.now().millisecondsSinceEpoch, + }); + } + + Future getAccessAttemptsTodayCount(String packageName) async { + final db = await database; + final todayStart = DateTime.now() + .subtract(const Duration(hours: 24)) + .millisecondsSinceEpoch; + final result = await db.rawQuery( + 'SELECT COUNT(*) as cnt FROM access_log WHERE package_name = ? AND attempted_at > ? AND was_allowed = 0', + [packageName, todayStart], + ); + return result.first['cnt'] as int? ?? 0; + } + + Future _createVpnTables(Database db) async { + await db.execute(''' + CREATE TABLE IF NOT EXISTS scam_domains ( + id INTEGER PRIMARY KEY AUTOINCREMENT, + domain TEXT UNIQUE NOT NULL, + category TEXT NOT NULL, + source TEXT NOT NULL, + hit_count INTEGER DEFAULT 0, + last_hit INTEGER, + created_at INTEGER NOT NULL + ) + '''); + + await db.execute(''' + CREATE TABLE IF NOT EXISTS vpn_events ( + id INTEGER PRIMARY KEY AUTOINCREMENT, + event_type TEXT NOT NULL, + domain TEXT, + category TEXT, + app_package TEXT, + created_at INTEGER NOT NULL + ) + '''); + } + + Future _seedScamDomains(Database db) async { + try { + final String contents = await rootBundle.loadString('assets/blocklist/india_scam_domains.txt'); + final lines = const LineSplitter().convert(contents); + + Batch batch = db.batch(); + String currentCategory = 'Known Scam Domain'; + + for (var line in lines) { + final clean = line.trim().toLowerCase(); + if (clean.isEmpty) continue; + if (clean.startsWith('#')) { + currentCategory = clean.substring(1).trim(); + continue; + } + + batch.insert('scam_domains', { + 'domain': clean, + 'category': currentCategory, + 'source': 'seed', + 'hit_count': 0, + 'created_at': DateTime.now().millisecondsSinceEpoch, + }, conflictAlgorithm: ConflictAlgorithm.ignore); + } + + await batch.commit(noResult: true); + } catch (e) { + print('Error seeding scam domains: $e'); + } + } +} diff --git a/lib/services/telemetry_service.dart b/lib/services/telemetry_service.dart new file mode 100644 index 0000000000000000000000000000000000000000..dfe3721e98b5c409fb258af4d88ae67923e5a3c2 --- /dev/null +++ b/lib/services/telemetry_service.dart @@ -0,0 +1,132 @@ +import 'dart:convert'; +import 'package:flutter/services.dart'; + +class SensorAccess { + final String packageName; + final String appName; + final String sensor; + final bool isActive; + + SensorAccess({required this.packageName, required this.appName, required this.sensor, required this.isActive}); + + factory SensorAccess.fromMap(Map map) { + return SensorAccess( + packageName: map['packageName'] ?? '', + appName: map['appName'] ?? '', + sensor: map['sensor'] ?? '', + isActive: map['isActive'] ?? false, + ); + } +} + +class AppPermissionStat { + final String packageName; + final String appName; + final Map accessCounts; + final bool isSystemApp; + + AppPermissionStat({required this.packageName, required this.appName, required this.accessCounts, required this.isSystemApp}); + + factory AppPermissionStat.fromMap(Map map) { + return AppPermissionStat( + packageName: map['packageName'] ?? '', + appName: map['appName'] ?? '', + accessCounts: Map.from(map['accessCounts'] ?? {}), + isSystemApp: map['isSystemApp'] ?? false, + ); + } +} + +class AppDataUsage { + final String packageName; + final String appName; + final int bytesSent; + final double mbSent; + + AppDataUsage({required this.packageName, required this.appName, required this.bytesSent, required this.mbSent}); + + factory AppDataUsage.fromMap(Map map) { + return AppDataUsage( + packageName: map['packageName'] ?? '', + appName: map['appName'] ?? '', + bytesSent: map['bytesSent'] is int ? map['bytesSent'] : (map['bytesSent'] as num?)?.toInt() ?? 0, + mbSent: map['mbSent'] as double? ?? 0.0, + ); + } +} + +class PrivacyStory { + final String severity; + final String emoji; + final String english; + final String hindi; + final String packageName; + + PrivacyStory({ + required this.severity, + required this.emoji, + required this.english, + required this.hindi, + required this.packageName, + }); + + factory PrivacyStory.fromMap(Map map) { + return PrivacyStory( + severity: map['severity'] ?? 'SAFE', + emoji: map['emoji'] ?? '', + english: map['english'] ?? '', + hindi: map['hindi'] ?? '', + packageName: map['packageName'] ?? '', + ); + } +} + +class TelemetryService { + static const _channel = MethodChannel('in.inmodel.premithius/telemetry'); + + static Future> getPrivacyStories() async { + try { + final jsonStr = await _channel.invokeMethod('getPrivacyStories'); + final list = jsonDecode(jsonStr as String) as List; + return list.map((e) => PrivacyStory.fromMap(e as Map)).toList(); + } catch (e) { + return [ + PrivacyStory( + severity: 'SAFE', + emoji: '✅', + english: 'Grant Usage Access to enable full privacy stories', + hindi: 'पूरी जानकारी के लिए Usage Access दें', + packageName: '', + ) + ]; + } + } + + static Future hasUsagePermission() async { + try { + return await _channel.invokeMethod('hasUsagePermission') as bool? ?? false; + } catch (e) { + return false; + } + } + + static Future> getDataUsage() async { + try { + final jsonStr = await _channel.invokeMethod('getDataUsage'); + final list = jsonDecode(jsonStr as String) as List; + return list.map((e) => AppDataUsage.fromMap(e as Map)).toList(); + } catch (e) { + return []; + } + } + + static Future> getActiveSensors() async { + try { + final jsonStr = await _channel.invokeMethod('getActiveSensors'); + final list = jsonDecode(jsonStr as String) as List; + return list.map((e) => SensorAccess.fromMap(e as Map)).toList(); + } catch (e) { + return []; + } + } +} diff --git a/lib/services/vector_service.dart b/lib/services/vector_service.dart new file mode 100644 index 0000000000000000000000000000000000000000..6675d698ad6da141dec929908f7b330203371dbd --- /dev/null +++ b/lib/services/vector_service.dart @@ -0,0 +1,199 @@ +import 'dart:convert'; +import 'package:flutter/services.dart'; +import 'package:sqflite/sqflite.dart'; + +/// Result of a vector-similarity search against the scam_embeddings table. +class VectorMatch { + final String category; + final double distance; + final bool isHighRisk; + final bool isMediumRisk; + + bool get isScam => isMediumRisk || isHighRisk; + String get threatLevel => isHighRisk ? 'HIGH' : isMediumRisk ? 'MEDIUM' : 'LOW'; + + VectorMatch({ + required this.category, + required this.distance, + required this.isHighRisk, + required this.isMediumRisk, + }); +} + +/// Encapsulates sqlite-vec Layer 2 of the Kavacha pipeline. +/// +/// Design principle: NEVER throw out. All failures are caught and logged. +/// The pipeline must continue with layers 1, 3, 4 if this layer is unavailable. +class VectorService { + static final VectorService _instance = VectorService._internal(); + factory VectorService() => _instance; + VectorService._internal(); + + static bool _isReady = false; + static bool get isReady => _isReady; + + /// The sqlite-vec version string, available after successful [initialize]. + static String vecVersion = 'not loaded'; + + /// Initialize the sqlite-vec extension and create the virtual table. + /// + /// Must be called once, after the database is opened, before the pipeline runs. + /// Safe to call multiple times — subsequent calls are no-ops. + static Future initialize(Database db) async { + if (_isReady) return; + try { + // CRITICAL: enable_load_extension MUST come before load_extension. + // SQLite on Android disables extension loading by default. + await db.execute("PRAGMA enable_load_extension = 1"); + await db.execute("SELECT load_extension('libsqlitevec')"); + await db.execute("PRAGMA enable_load_extension = 0"); + + // Verify extension loaded correctly. + final version = await db.rawQuery("SELECT vec_version()"); + vecVersion = version.first.values.first?.toString() ?? 'unknown'; + print('[VectorService] sqlite-vec version: $vecVersion'); + + // Create virtual vector table for scam embeddings (128-dimension). + await db.execute(''' + CREATE VIRTUAL TABLE IF NOT EXISTS scam_embeddings + USING vec0( + embedding FLOAT[384], + +category TEXT, + +source TEXT, + +created_at INTEGER + ) + '''); + + _isReady = true; + print('[VectorService] Layer 2 ready'); + } catch (e) { + _isReady = false; + vecVersion = 'not loaded'; + print('[VectorService] Failed to load: $e'); + print('[VectorService] Layer 2 disabled — pipeline continues without it'); + // Do NOT rethrow — Kavacha pipeline must continue with layers 1, 3, 4. + } + } + + /// Store a confirmed scam as an embedding for future matching. + Future addScamEmbedding({ + required Database db, + required List embedding, + required String category, + required String source, + }) async { + if (!_isReady) return; + try { + await db.execute( + 'INSERT INTO scam_embeddings(embedding, category, source, created_at) VALUES (?, ?, ?, ?)', + [ + '[${embedding.join(',')}]', + category, + source, + DateTime.now().millisecondsSinceEpoch, + ], + ); + } catch (e) { + print('[VectorService] addScamEmbedding error: $e'); + } + } + + /// Find the closest scam pattern in the embedding store. + /// + /// Returns [VectorMatch] if a candidate is found, [null] if not or layer is disabled. + Future findClosest({ + required Database db, + required List queryEmbedding, + double highRiskThreshold = 0.15, + double mediumRiskThreshold = 0.35, + }) async { + if (!_isReady) return null; + try { + final results = await db.rawQuery(''' + SELECT category, source, distance + FROM scam_embeddings + WHERE embedding MATCH ? + ORDER BY distance + LIMIT 1 + ''', ['[${queryEmbedding.join(',')}]']); + + if (results.isEmpty) return null; + + final distance = (results.first['distance'] as num).toDouble(); + final category = results.first['category'] as String; + + return VectorMatch( + category: category, + distance: distance, + isHighRisk: distance < highRiskThreshold, + isMediumRisk: distance < mediumRiskThreshold, + ); + } catch (e) { + print('[VectorService] findClosest error: $e'); + return null; + } + } + + /// Convenience accessor that uses StorageService's shared DB. + Future findClosestScam(List queryEmbedding) async { + if (!_isReady) return null; + // This path is used by layer2_vector.dart which has its own db reference. + // The caller passes the embedding; DB must be provided via findClosest(). + // Return null here to signal the caller to use findClosest() directly. + return null; + } + + /// Seed the vector store with pre-computed scam embeddings from a JSON asset. + /// + /// Call once on first install. Skips silently if embeddings already exist. + Future seedEmbeddings(Database db, String assetPath) async { + if (!_isReady) return; + try { + final countResult = await db.rawQuery( + 'SELECT COUNT(*) as c FROM scam_embeddings', + ); + final existing = (countResult.first['c'] as int); + if (existing > 0) { + print('[VectorService] Already seeded ($existing embeddings), skipping'); + return; + } + + print('[VectorService] Seeding embeddings from $assetPath'); + final String jsonString = await rootBundle.loadString(assetPath); + final List data = jsonDecode(jsonString); + + final batch = db.batch(); + for (final item in data) { + final List rawEmbedding = item['embedding'] as List; + final embeddingStr = + '[${rawEmbedding.map((v) => (v as num).toDouble()).join(',')}]'; + batch.execute( + 'INSERT INTO scam_embeddings(embedding, category, source, created_at) VALUES (?, ?, ?, ?)', + [ + embeddingStr, + item['category'] as String, + item['source'] as String, + DateTime.now().millisecondsSinceEpoch, + ], + ); + } + await batch.commit(noResult: true); + print('[VectorService] Seeded ${data.length} embeddings'); + } catch (e) { + print('[VectorService] Seed error: $e'); + } + } + + /// Returns the count of embeddings currently in the store. + Future embeddingCount(Database db) async { + if (!_isReady) return 0; + try { + final result = await db.rawQuery( + 'SELECT COUNT(*) as c FROM scam_embeddings', + ); + return (result.first['c'] as int); + } catch (_) { + return 0; + } + } +} diff --git a/lib/services/vpn_service.dart b/lib/services/vpn_service.dart new file mode 100644 index 0000000000000000000000000000000000000000..5a5f9973e594f29368166188401e5c081eca8e66 --- /dev/null +++ b/lib/services/vpn_service.dart @@ -0,0 +1,78 @@ +import 'package:flutter/services.dart'; +import 'package:premithus/services/storage_service.dart'; + +class VpnStats { + final int blockedToday; + final String? lastBlockedDomain; + final String? lastBlockedCategory; + final List topBlockedDomains; + + VpnStats({ + required this.blockedToday, + this.lastBlockedDomain, + this.lastBlockedCategory, + required this.topBlockedDomains, + }); +} + +class BlockedDomain { + final String domain; + final int hitCount; + + BlockedDomain({required this.domain, required this.hitCount}); +} + +class KavachaVpn { + static const _channel = MethodChannel('in.inmodel.premithius/vpn'); + static bool _isRunning = false; + static bool get isRunning => _isRunning; + + static Future start() async { + final result = await _channel.invokeMethod('startVpn'); + _isRunning = result == 'started'; + } + + static Future stop() async { + await _channel.invokeMethod('stopVpn'); + _isRunning = false; + } + + static Future getStats() async { + final db = await StorageService().database; + final today = DateTime.now().millisecondsSinceEpoch - 86400000; + + final blocked = await db.rawQuery( + 'SELECT COUNT(*) as c FROM vpn_events WHERE event_type="blocked" AND created_at > ?', + [today] + ); + final lastBlocked = await db.rawQuery( + 'SELECT domain, category, created_at FROM vpn_events WHERE event_type="blocked" ORDER BY created_at DESC LIMIT 1' + ); + final topDomains = await db.rawQuery( + 'SELECT domain, hit_count FROM scam_domains ORDER BY hit_count DESC LIMIT 5' + ); + + int count = 0; + if (blocked.isNotEmpty && blocked.first['c'] != null) { + count = blocked.first['c'] as int; + } + + return VpnStats( + blockedToday: count, + lastBlockedDomain: lastBlocked.isNotEmpty ? lastBlocked.first['domain'] as String : null, + lastBlockedCategory: lastBlocked.isNotEmpty ? lastBlocked.first['category'] as String : null, + topBlockedDomains: topDomains.map((r) => BlockedDomain( + domain: r['domain'] as String, + hitCount: r['hit_count'] as int, + )).toList(), + ); + } + + static Future getLastEvent() async { + return await _channel.invokeMethod('getLastEvent'); + } + + static Future reloadBlocklist() async { + await _channel.invokeMethod('reloadBlocklist'); + } +} diff --git a/lib/theme/finanjo_theme.dart b/lib/theme/finanjo_theme.dart new file mode 100644 index 0000000000000000000000000000000000000000..da32f72d0f791ef52ef44efebcf1500a6b2a36b1 --- /dev/null +++ b/lib/theme/finanjo_theme.dart @@ -0,0 +1,143 @@ +import 'package:flutter/material.dart'; + +class FinanjoTheme { + // Brand Colors - Tuned to be cleaner and slightly deeper + static const Color primaryPurple = Color(0xFF6C43D5); + static const Color lightPurple = Color(0xFFE2D6F5); + static const Color deepPurple = Color(0xFF33157A); + static const Color backgroundLight = Color(0xFFFAF9FC); + static const Color cardWhite = Colors.white; + static const Color textDark = Color(0xFF141029); + static const Color textGrey = Color(0xFF6B6580); + static const Color successGreen = Color(0xFF00C48C); + static const Color cautionYellow = Color(0xFFFFB800); + + // Gradient Background - softer, more majestic + static const LinearGradient premiumGradient = LinearGradient( + begin: Alignment.topLeft, + end: Alignment.bottomRight, + colors: [ + Color(0xFFEDE6FB), // Very light soft purple + Color(0xFFFFFFFF), // Pure white + Color(0xFFE8DEFA), // Very light soft purple + ], + stops: [0.0, 0.5, 1.0], + ); + + static const LinearGradient solidPremiumGradient = LinearGradient( + begin: Alignment.topCenter, + end: Alignment.bottomCenter, + colors: [ + Color(0xFF8B6BCE), + Color(0xFF6C43D5), + ], + ); + + // Box Decorations - ultra premium layered shadows + static BoxDecoration cardDecoration = BoxDecoration( + color: cardWhite, + borderRadius: BorderRadius.circular(32), + boxShadow: [ + BoxShadow( + color: primaryPurple.withOpacity(0.06), + blurRadius: 35, + offset: const Offset(0, 20), + spreadRadius: 2, + ), + BoxShadow( + color: Colors.black.withOpacity(0.02), + blurRadius: 10, + offset: const Offset(0, 5), + ), + ], + ); + + static BoxDecoration glassDecoration = BoxDecoration( + color: Colors.white.withOpacity(0.85), + borderRadius: BorderRadius.circular(32), + border: Border.all(color: Colors.white.withOpacity(0.4), width: 1.5), + boxShadow: [ + BoxShadow( + color: deepPurple.withOpacity(0.04), + blurRadius: 40, + offset: const Offset(0, 15), + ), + ], + ); + + // Button Styles - more distinct "pill" feel and heft + static ButtonStyle primaryButtonStyle = ElevatedButton.styleFrom( + backgroundColor: primaryPurple, + foregroundColor: Colors.white, + elevation: 0, + shape: RoundedRectangleBorder( + borderRadius: BorderRadius.circular(24), + ), + padding: const EdgeInsets.symmetric(horizontal: 40, vertical: 18), + textStyle: const TextStyle( + fontSize: 17, + fontWeight: FontWeight.w800, + letterSpacing: 0.3, + ), + ); + + static ButtonStyle secondaryButtonStyle = OutlinedButton.styleFrom( + foregroundColor: primaryPurple, + side: const BorderSide(color: primaryPurple, width: 2), + shape: RoundedRectangleBorder( + borderRadius: BorderRadius.circular(24), + ), + padding: const EdgeInsets.symmetric(horizontal: 40, vertical: 18), + textStyle: const TextStyle( + fontSize: 17, + fontWeight: FontWeight.w800, + ), + ); + + // Text Styles - cleaner layouts + static const TextStyle headingStyle = TextStyle( + color: textDark, + fontSize: 34, + fontWeight: FontWeight.w900, + height: 1.15, + letterSpacing: -0.5, + ); + + static const TextStyle subHeadingStyle = TextStyle( + color: textGrey, + fontSize: 16, + fontWeight: FontWeight.w600, + height: 1.4, + ); + + static const TextStyle bodyStyle = TextStyle( + color: textGrey, + fontSize: 15, + fontWeight: FontWeight.w500, + height: 1.5, + ); + + // Overall App Theme + static ThemeData get themeData { + return ThemeData( + primaryColor: primaryPurple, + scaffoldBackgroundColor: backgroundLight, + colorScheme: ColorScheme.fromSeed(seedColor: primaryPurple), + fontFamily: 'Roboto', // Safe universal bet for clean sans-serif + appBarTheme: const AppBarTheme( + backgroundColor: Colors.transparent, + elevation: 0, + centerTitle: true, + iconTheme: IconThemeData(color: deepPurple), + titleTextStyle: TextStyle( + color: textDark, + fontSize: 18, + fontWeight: FontWeight.w800, + ), + ), + elevatedButtonTheme: ElevatedButtonThemeData(style: primaryButtonStyle), + outlinedButtonTheme: OutlinedButtonThemeData(style: secondaryButtonStyle), + useMaterial3: true, + ); + } +} diff --git a/linux/.gitignore b/linux/.gitignore new file mode 100644 index 0000000000000000000000000000000000000000..d3896c98444fbe7288d434169a28c532258a4466 --- /dev/null +++ b/linux/.gitignore @@ -0,0 +1 @@ +flutter/ephemeral diff --git a/linux/CMakeLists.txt b/linux/CMakeLists.txt new file mode 100644 index 0000000000000000000000000000000000000000..9eb21013bc063075de04339e0573c3e591de72d2 --- /dev/null +++ b/linux/CMakeLists.txt @@ -0,0 +1,128 @@ +# Project-level configuration. +cmake_minimum_required(VERSION 3.13) +project(runner LANGUAGES CXX) + +# The name of the executable created for the application. Change this to change +# the on-disk name of your application. +set(BINARY_NAME "premithus") +# The unique GTK application identifier for this application. See: +# https://wiki.gnome.org/HowDoI/ChooseApplicationID +set(APPLICATION_ID "in.inmodel.premithus") + +# Explicitly opt in to modern CMake behaviors to avoid warnings with recent +# versions of CMake. +cmake_policy(SET CMP0063 NEW) + +# Load bundled libraries from the lib/ directory relative to the binary. +set(CMAKE_INSTALL_RPATH "$ORIGIN/lib") + +# Root filesystem for cross-building. +if(FLUTTER_TARGET_PLATFORM_SYSROOT) + set(CMAKE_SYSROOT ${FLUTTER_TARGET_PLATFORM_SYSROOT}) + set(CMAKE_FIND_ROOT_PATH ${CMAKE_SYSROOT}) + set(CMAKE_FIND_ROOT_PATH_MODE_PROGRAM NEVER) + set(CMAKE_FIND_ROOT_PATH_MODE_PACKAGE ONLY) + set(CMAKE_FIND_ROOT_PATH_MODE_LIBRARY ONLY) + set(CMAKE_FIND_ROOT_PATH_MODE_INCLUDE ONLY) +endif() + +# Define build configuration options. +if(NOT CMAKE_BUILD_TYPE AND NOT CMAKE_CONFIGURATION_TYPES) + set(CMAKE_BUILD_TYPE "Debug" CACHE + STRING "Flutter build mode" FORCE) + set_property(CACHE CMAKE_BUILD_TYPE PROPERTY STRINGS + "Debug" "Profile" "Release") +endif() + +# Compilation settings that should be applied to most targets. +# +# Be cautious about adding new options here, as plugins use this function by +# default. In most cases, you should add new options to specific targets instead +# of modifying this function. +function(APPLY_STANDARD_SETTINGS TARGET) + target_compile_features(${TARGET} PUBLIC cxx_std_14) + target_compile_options(${TARGET} PRIVATE -Wall -Werror) + target_compile_options(${TARGET} PRIVATE "$<$>:-O3>") + target_compile_definitions(${TARGET} PRIVATE "$<$>:NDEBUG>") +endfunction() + +# Flutter library and tool build rules. +set(FLUTTER_MANAGED_DIR "${CMAKE_CURRENT_SOURCE_DIR}/flutter") +add_subdirectory(${FLUTTER_MANAGED_DIR}) + +# System-level dependencies. +find_package(PkgConfig REQUIRED) +pkg_check_modules(GTK REQUIRED IMPORTED_TARGET gtk+-3.0) + +# Application build; see runner/CMakeLists.txt. +add_subdirectory("runner") + +# Run the Flutter tool portions of the build. This must not be removed. +add_dependencies(${BINARY_NAME} flutter_assemble) + +# Only the install-generated bundle's copy of the executable will launch +# correctly, since the resources must in the right relative locations. To avoid +# people trying to run the unbundled copy, put it in a subdirectory instead of +# the default top-level location. +set_target_properties(${BINARY_NAME} + PROPERTIES + RUNTIME_OUTPUT_DIRECTORY "${CMAKE_BINARY_DIR}/intermediates_do_not_run" +) + + +# Generated plugin build rules, which manage building the plugins and adding +# them to the application. +include(flutter/generated_plugins.cmake) + + +# === Installation === +# By default, "installing" just makes a relocatable bundle in the build +# directory. +set(BUILD_BUNDLE_DIR "${PROJECT_BINARY_DIR}/bundle") +if(CMAKE_INSTALL_PREFIX_INITIALIZED_TO_DEFAULT) + set(CMAKE_INSTALL_PREFIX "${BUILD_BUNDLE_DIR}" CACHE PATH "..." FORCE) +endif() + +# Start with a clean build bundle directory every time. +install(CODE " + file(REMOVE_RECURSE \"${BUILD_BUNDLE_DIR}/\") + " COMPONENT Runtime) + +set(INSTALL_BUNDLE_DATA_DIR "${CMAKE_INSTALL_PREFIX}/data") +set(INSTALL_BUNDLE_LIB_DIR "${CMAKE_INSTALL_PREFIX}/lib") + +install(TARGETS ${BINARY_NAME} RUNTIME DESTINATION "${CMAKE_INSTALL_PREFIX}" + COMPONENT Runtime) + +install(FILES "${FLUTTER_ICU_DATA_FILE}" DESTINATION "${INSTALL_BUNDLE_DATA_DIR}" + COMPONENT Runtime) + +install(FILES "${FLUTTER_LIBRARY}" DESTINATION "${INSTALL_BUNDLE_LIB_DIR}" + COMPONENT Runtime) + +foreach(bundled_library ${PLUGIN_BUNDLED_LIBRARIES}) + install(FILES "${bundled_library}" + DESTINATION "${INSTALL_BUNDLE_LIB_DIR}" + COMPONENT Runtime) +endforeach(bundled_library) + +# Copy the native assets provided by the build.dart from all packages. +set(NATIVE_ASSETS_DIR "${PROJECT_BUILD_DIR}native_assets/linux/") +install(DIRECTORY "${NATIVE_ASSETS_DIR}" + DESTINATION "${INSTALL_BUNDLE_LIB_DIR}" + COMPONENT Runtime) + +# Fully re-copy the assets directory on each build to avoid having stale files +# from a previous install. +set(FLUTTER_ASSET_DIR_NAME "flutter_assets") +install(CODE " + file(REMOVE_RECURSE \"${INSTALL_BUNDLE_DATA_DIR}/${FLUTTER_ASSET_DIR_NAME}\") + " COMPONENT Runtime) +install(DIRECTORY "${PROJECT_BUILD_DIR}/${FLUTTER_ASSET_DIR_NAME}" + DESTINATION "${INSTALL_BUNDLE_DATA_DIR}" COMPONENT Runtime) + +# Install the AOT library on non-Debug builds only. +if(NOT CMAKE_BUILD_TYPE MATCHES "Debug") + install(FILES "${AOT_LIBRARY}" DESTINATION "${INSTALL_BUNDLE_LIB_DIR}" + COMPONENT Runtime) +endif() diff --git a/linux/flutter/CMakeLists.txt b/linux/flutter/CMakeLists.txt new file mode 100644 index 0000000000000000000000000000000000000000..d5bd01648a96d50136b2a97c8bb9aa5b711f6c39 --- /dev/null +++ b/linux/flutter/CMakeLists.txt @@ -0,0 +1,88 @@ +# This file controls Flutter-level build steps. It should not be edited. +cmake_minimum_required(VERSION 3.10) + +set(EPHEMERAL_DIR "${CMAKE_CURRENT_SOURCE_DIR}/ephemeral") + +# Configuration provided via flutter tool. +include(${EPHEMERAL_DIR}/generated_config.cmake) + +# TODO: Move the rest of this into files in ephemeral. See +# https://github.com/flutter/flutter/issues/57146. + +# Serves the same purpose as list(TRANSFORM ... PREPEND ...), +# which isn't available in 3.10. +function(list_prepend LIST_NAME PREFIX) + set(NEW_LIST "") + foreach(element ${${LIST_NAME}}) + list(APPEND NEW_LIST "${PREFIX}${element}") + endforeach(element) + set(${LIST_NAME} "${NEW_LIST}" PARENT_SCOPE) +endfunction() + +# === Flutter Library === +# System-level dependencies. +find_package(PkgConfig REQUIRED) +pkg_check_modules(GTK REQUIRED IMPORTED_TARGET gtk+-3.0) +pkg_check_modules(GLIB REQUIRED IMPORTED_TARGET glib-2.0) +pkg_check_modules(GIO REQUIRED IMPORTED_TARGET gio-2.0) + +set(FLUTTER_LIBRARY "${EPHEMERAL_DIR}/libflutter_linux_gtk.so") + +# Published to parent scope for install step. +set(FLUTTER_LIBRARY ${FLUTTER_LIBRARY} PARENT_SCOPE) +set(FLUTTER_ICU_DATA_FILE "${EPHEMERAL_DIR}/icudtl.dat" PARENT_SCOPE) +set(PROJECT_BUILD_DIR "${PROJECT_DIR}/build/" PARENT_SCOPE) +set(AOT_LIBRARY "${PROJECT_DIR}/build/lib/libapp.so" PARENT_SCOPE) + +list(APPEND FLUTTER_LIBRARY_HEADERS + "fl_basic_message_channel.h" + "fl_binary_codec.h" + "fl_binary_messenger.h" + "fl_dart_project.h" + "fl_engine.h" + "fl_json_message_codec.h" + "fl_json_method_codec.h" + "fl_message_codec.h" + "fl_method_call.h" + "fl_method_channel.h" + "fl_method_codec.h" + "fl_method_response.h" + "fl_plugin_registrar.h" + "fl_plugin_registry.h" + "fl_standard_message_codec.h" + "fl_standard_method_codec.h" + "fl_string_codec.h" + "fl_value.h" + "fl_view.h" + "flutter_linux.h" +) +list_prepend(FLUTTER_LIBRARY_HEADERS "${EPHEMERAL_DIR}/flutter_linux/") +add_library(flutter INTERFACE) +target_include_directories(flutter INTERFACE + "${EPHEMERAL_DIR}" +) +target_link_libraries(flutter INTERFACE "${FLUTTER_LIBRARY}") +target_link_libraries(flutter INTERFACE + PkgConfig::GTK + PkgConfig::GLIB + PkgConfig::GIO +) +add_dependencies(flutter flutter_assemble) + +# === Flutter tool backend === +# _phony_ is a non-existent file to force this command to run every time, +# since currently there's no way to get a full input/output list from the +# flutter tool. +add_custom_command( + OUTPUT ${FLUTTER_LIBRARY} ${FLUTTER_LIBRARY_HEADERS} + ${CMAKE_CURRENT_BINARY_DIR}/_phony_ + COMMAND ${CMAKE_COMMAND} -E env + ${FLUTTER_TOOL_ENVIRONMENT} + "${FLUTTER_ROOT}/packages/flutter_tools/bin/tool_backend.sh" + ${FLUTTER_TARGET_PLATFORM} ${CMAKE_BUILD_TYPE} + VERBATIM +) +add_custom_target(flutter_assemble DEPENDS + "${FLUTTER_LIBRARY}" + ${FLUTTER_LIBRARY_HEADERS} +) diff --git a/linux/flutter/generated_plugin_registrant.cc b/linux/flutter/generated_plugin_registrant.cc new file mode 100644 index 0000000000000000000000000000000000000000..e71a16d23d05881b554326e645083799ab9bfc5e --- /dev/null +++ b/linux/flutter/generated_plugin_registrant.cc @@ -0,0 +1,11 @@ +// +// Generated file. Do not edit. +// + +// clang-format off + +#include "generated_plugin_registrant.h" + + +void fl_register_plugins(FlPluginRegistry* registry) { +} diff --git a/linux/flutter/generated_plugin_registrant.h b/linux/flutter/generated_plugin_registrant.h new file mode 100644 index 0000000000000000000000000000000000000000..e0f0a47bc08f30b550b47b01de4c9206b6824dd9 --- /dev/null +++ b/linux/flutter/generated_plugin_registrant.h @@ -0,0 +1,15 @@ +// +// Generated file. Do not edit. +// + +// clang-format off + +#ifndef GENERATED_PLUGIN_REGISTRANT_ +#define GENERATED_PLUGIN_REGISTRANT_ + +#include + +// Registers Flutter plugins. +void fl_register_plugins(FlPluginRegistry* registry); + +#endif // GENERATED_PLUGIN_REGISTRANT_ diff --git a/linux/flutter/generated_plugins.cmake b/linux/flutter/generated_plugins.cmake new file mode 100644 index 0000000000000000000000000000000000000000..cf3f2cbed95255fcc9ba3cb2cb4a153894f738b6 --- /dev/null +++ b/linux/flutter/generated_plugins.cmake @@ -0,0 +1,24 @@ +# +# Generated file, do not edit. +# + +list(APPEND FLUTTER_PLUGIN_LIST +) + +list(APPEND FLUTTER_FFI_PLUGIN_LIST + tflite_flutter +) + +set(PLUGIN_BUNDLED_LIBRARIES) + +foreach(plugin ${FLUTTER_PLUGIN_LIST}) + add_subdirectory(flutter/ephemeral/.plugin_symlinks/${plugin}/linux plugins/${plugin}) + target_link_libraries(${BINARY_NAME} PRIVATE ${plugin}_plugin) + list(APPEND PLUGIN_BUNDLED_LIBRARIES $) + list(APPEND PLUGIN_BUNDLED_LIBRARIES ${${plugin}_bundled_libraries}) +endforeach(plugin) + +foreach(ffi_plugin ${FLUTTER_FFI_PLUGIN_LIST}) + add_subdirectory(flutter/ephemeral/.plugin_symlinks/${ffi_plugin}/linux plugins/${ffi_plugin}) + list(APPEND PLUGIN_BUNDLED_LIBRARIES ${${ffi_plugin}_bundled_libraries}) +endforeach(ffi_plugin) diff --git a/linux/runner/CMakeLists.txt b/linux/runner/CMakeLists.txt new file mode 100644 index 0000000000000000000000000000000000000000..e97dabc7028e16c6d9ec74f1e2fb677a93ba81b5 --- /dev/null +++ b/linux/runner/CMakeLists.txt @@ -0,0 +1,26 @@ +cmake_minimum_required(VERSION 3.13) +project(runner LANGUAGES CXX) + +# Define the application target. To change its name, change BINARY_NAME in the +# top-level CMakeLists.txt, not the value here, or `flutter run` will no longer +# work. +# +# Any new source files that you add to the application should be added here. +add_executable(${BINARY_NAME} + "main.cc" + "my_application.cc" + "${FLUTTER_MANAGED_DIR}/generated_plugin_registrant.cc" +) + +# Apply the standard set of build settings. This can be removed for applications +# that need different build settings. +apply_standard_settings(${BINARY_NAME}) + +# Add preprocessor definitions for the application ID. +add_definitions(-DAPPLICATION_ID="${APPLICATION_ID}") + +# Add dependency libraries. Add any application-specific dependencies here. +target_link_libraries(${BINARY_NAME} PRIVATE flutter) +target_link_libraries(${BINARY_NAME} PRIVATE PkgConfig::GTK) + +target_include_directories(${BINARY_NAME} PRIVATE "${CMAKE_SOURCE_DIR}") diff --git a/linux/runner/main.cc b/linux/runner/main.cc new file mode 100644 index 0000000000000000000000000000000000000000..e7c5c54370372a4cdde7288a32733998d87bd767 --- /dev/null +++ b/linux/runner/main.cc @@ -0,0 +1,6 @@ +#include "my_application.h" + +int main(int argc, char** argv) { + g_autoptr(MyApplication) app = my_application_new(); + return g_application_run(G_APPLICATION(app), argc, argv); +} diff --git a/linux/runner/my_application.cc b/linux/runner/my_application.cc new file mode 100644 index 0000000000000000000000000000000000000000..17c6027c208e74335ad0bfb074a7e8c106f2f2bd --- /dev/null +++ b/linux/runner/my_application.cc @@ -0,0 +1,148 @@ +#include "my_application.h" + +#include +#ifdef GDK_WINDOWING_X11 +#include +#endif + +#include "flutter/generated_plugin_registrant.h" + +struct _MyApplication { + GtkApplication parent_instance; + char** dart_entrypoint_arguments; +}; + +G_DEFINE_TYPE(MyApplication, my_application, GTK_TYPE_APPLICATION) + +// Called when first Flutter frame received. +static void first_frame_cb(MyApplication* self, FlView* view) { + gtk_widget_show(gtk_widget_get_toplevel(GTK_WIDGET(view))); +} + +// Implements GApplication::activate. +static void my_application_activate(GApplication* application) { + MyApplication* self = MY_APPLICATION(application); + GtkWindow* window = + GTK_WINDOW(gtk_application_window_new(GTK_APPLICATION(application))); + + // Use a header bar when running in GNOME as this is the common style used + // by applications and is the setup most users will be using (e.g. Ubuntu + // desktop). + // If running on X and not using GNOME then just use a traditional title bar + // in case the window manager does more exotic layout, e.g. tiling. + // If running on Wayland assume the header bar will work (may need changing + // if future cases occur). + gboolean use_header_bar = TRUE; +#ifdef GDK_WINDOWING_X11 + GdkScreen* screen = gtk_window_get_screen(window); + if (GDK_IS_X11_SCREEN(screen)) { + const gchar* wm_name = gdk_x11_screen_get_window_manager_name(screen); + if (g_strcmp0(wm_name, "GNOME Shell") != 0) { + use_header_bar = FALSE; + } + } +#endif + if (use_header_bar) { + GtkHeaderBar* header_bar = GTK_HEADER_BAR(gtk_header_bar_new()); + gtk_widget_show(GTK_WIDGET(header_bar)); + gtk_header_bar_set_title(header_bar, "premithus"); + gtk_header_bar_set_show_close_button(header_bar, TRUE); + gtk_window_set_titlebar(window, GTK_WIDGET(header_bar)); + } else { + gtk_window_set_title(window, "premithus"); + } + + gtk_window_set_default_size(window, 1280, 720); + + g_autoptr(FlDartProject) project = fl_dart_project_new(); + fl_dart_project_set_dart_entrypoint_arguments( + project, self->dart_entrypoint_arguments); + + FlView* view = fl_view_new(project); + GdkRGBA background_color; + // Background defaults to black, override it here if necessary, e.g. #00000000 + // for transparent. + gdk_rgba_parse(&background_color, "#000000"); + fl_view_set_background_color(view, &background_color); + gtk_widget_show(GTK_WIDGET(view)); + gtk_container_add(GTK_CONTAINER(window), GTK_WIDGET(view)); + + // Show the window when Flutter renders. + // Requires the view to be realized so we can start rendering. + g_signal_connect_swapped(view, "first-frame", G_CALLBACK(first_frame_cb), + self); + gtk_widget_realize(GTK_WIDGET(view)); + + fl_register_plugins(FL_PLUGIN_REGISTRY(view)); + + gtk_widget_grab_focus(GTK_WIDGET(view)); +} + +// Implements GApplication::local_command_line. +static gboolean my_application_local_command_line(GApplication* application, + gchar*** arguments, + int* exit_status) { + MyApplication* self = MY_APPLICATION(application); + // Strip out the first argument as it is the binary name. + self->dart_entrypoint_arguments = g_strdupv(*arguments + 1); + + g_autoptr(GError) error = nullptr; + if (!g_application_register(application, nullptr, &error)) { + g_warning("Failed to register: %s", error->message); + *exit_status = 1; + return TRUE; + } + + g_application_activate(application); + *exit_status = 0; + + return TRUE; +} + +// Implements GApplication::startup. +static void my_application_startup(GApplication* application) { + // MyApplication* self = MY_APPLICATION(object); + + // Perform any actions required at application startup. + + G_APPLICATION_CLASS(my_application_parent_class)->startup(application); +} + +// Implements GApplication::shutdown. +static void my_application_shutdown(GApplication* application) { + // MyApplication* self = MY_APPLICATION(object); + + // Perform any actions required at application shutdown. + + G_APPLICATION_CLASS(my_application_parent_class)->shutdown(application); +} + +// Implements GObject::dispose. +static void my_application_dispose(GObject* object) { + MyApplication* self = MY_APPLICATION(object); + g_clear_pointer(&self->dart_entrypoint_arguments, g_strfreev); + G_OBJECT_CLASS(my_application_parent_class)->dispose(object); +} + +static void my_application_class_init(MyApplicationClass* klass) { + G_APPLICATION_CLASS(klass)->activate = my_application_activate; + G_APPLICATION_CLASS(klass)->local_command_line = + my_application_local_command_line; + G_APPLICATION_CLASS(klass)->startup = my_application_startup; + G_APPLICATION_CLASS(klass)->shutdown = my_application_shutdown; + G_OBJECT_CLASS(klass)->dispose = my_application_dispose; +} + +static void my_application_init(MyApplication* self) {} + +MyApplication* my_application_new() { + // Set the program name to the application ID, which helps various systems + // like GTK and desktop environments map this running application to its + // corresponding .desktop file. This ensures better integration by allowing + // the application to be recognized beyond its binary name. + g_set_prgname(APPLICATION_ID); + + return MY_APPLICATION(g_object_new(my_application_get_type(), + "application-id", APPLICATION_ID, "flags", + G_APPLICATION_NON_UNIQUE, nullptr)); +} diff --git a/linux/runner/my_application.h b/linux/runner/my_application.h new file mode 100644 index 0000000000000000000000000000000000000000..db16367a77d061e7c4b63e46b8aea134ade776d4 --- /dev/null +++ b/linux/runner/my_application.h @@ -0,0 +1,21 @@ +#ifndef FLUTTER_MY_APPLICATION_H_ +#define FLUTTER_MY_APPLICATION_H_ + +#include + +G_DECLARE_FINAL_TYPE(MyApplication, + my_application, + MY, + APPLICATION, + GtkApplication) + +/** + * my_application_new: + * + * Creates a new Flutter-based application. + * + * Returns: a new #MyApplication. + */ +MyApplication* my_application_new(); + +#endif // FLUTTER_MY_APPLICATION_H_ diff --git a/macos/.gitignore b/macos/.gitignore new file mode 100644 index 0000000000000000000000000000000000000000..746adbb6b9e14b7e685c91e280a4d37a672afbd8 --- /dev/null +++ b/macos/.gitignore @@ -0,0 +1,7 @@ +# Flutter-related +**/Flutter/ephemeral/ +**/Pods/ + +# Xcode-related +**/dgph +**/xcuserdata/ diff --git a/macos/Flutter/Flutter-Debug.xcconfig b/macos/Flutter/Flutter-Debug.xcconfig new file mode 100644 index 0000000000000000000000000000000000000000..4b81f9b2d200fc807eed25bca04dff9ee9dcc45f --- /dev/null +++ b/macos/Flutter/Flutter-Debug.xcconfig @@ -0,0 +1,2 @@ +#include? "Pods/Target Support Files/Pods-Runner/Pods-Runner.debug.xcconfig" +#include "ephemeral/Flutter-Generated.xcconfig" diff --git a/macos/Flutter/Flutter-Release.xcconfig b/macos/Flutter/Flutter-Release.xcconfig new file mode 100644 index 0000000000000000000000000000000000000000..5caa9d1579e481a5894c37e2e56b0da062e95b35 --- /dev/null +++ b/macos/Flutter/Flutter-Release.xcconfig @@ -0,0 +1,2 @@ +#include? "Pods/Target Support Files/Pods-Runner/Pods-Runner.release.xcconfig" +#include "ephemeral/Flutter-Generated.xcconfig" diff --git a/macos/Flutter/GeneratedPluginRegistrant.swift b/macos/Flutter/GeneratedPluginRegistrant.swift new file mode 100644 index 0000000000000000000000000000000000000000..29d4e7f0cc5c1b4a84a961b419875be6f1e2b31f --- /dev/null +++ b/macos/Flutter/GeneratedPluginRegistrant.swift @@ -0,0 +1,12 @@ +// +// Generated file. Do not edit. +// + +import FlutterMacOS +import Foundation + +import sqflite_darwin + +func RegisterGeneratedPlugins(registry: FlutterPluginRegistry) { + SqflitePlugin.register(with: registry.registrar(forPlugin: "SqflitePlugin")) +} diff --git a/macos/Podfile b/macos/Podfile new file mode 100644 index 0000000000000000000000000000000000000000..ff5ddb3b8bdcd02db4e59cb12b3488f81ea0bb09 --- /dev/null +++ b/macos/Podfile @@ -0,0 +1,42 @@ +platform :osx, '10.15' + +# CocoaPods analytics sends network stats synchronously affecting flutter build latency. +ENV['COCOAPODS_DISABLE_STATS'] = 'true' + +project 'Runner', { + 'Debug' => :debug, + 'Profile' => :release, + 'Release' => :release, +} + +def flutter_root + generated_xcode_build_settings_path = File.expand_path(File.join('..', 'Flutter', 'ephemeral', 'Flutter-Generated.xcconfig'), __FILE__) + unless File.exist?(generated_xcode_build_settings_path) + raise "#{generated_xcode_build_settings_path} must exist. If you're running pod install manually, make sure \"flutter pub get\" is executed first" + end + + File.foreach(generated_xcode_build_settings_path) do |line| + matches = line.match(/FLUTTER_ROOT\=(.*)/) + return matches[1].strip if matches + end + raise "FLUTTER_ROOT not found in #{generated_xcode_build_settings_path}. Try deleting Flutter-Generated.xcconfig, then run \"flutter pub get\"" +end + +require File.expand_path(File.join('packages', 'flutter_tools', 'bin', 'podhelper'), flutter_root) + +flutter_macos_podfile_setup + +target 'Runner' do + use_frameworks! + + flutter_install_all_macos_pods File.dirname(File.realpath(__FILE__)) + target 'RunnerTests' do + inherit! :search_paths + end +end + +post_install do |installer| + installer.pods_project.targets.each do |target| + flutter_additional_macos_build_settings(target) + end +end diff --git a/macos/Runner.xcodeproj/project.pbxproj b/macos/Runner.xcodeproj/project.pbxproj new file mode 100644 index 0000000000000000000000000000000000000000..d4b570ba837379ec1f12a8e9dae26a766377d908 --- /dev/null +++ b/macos/Runner.xcodeproj/project.pbxproj @@ -0,0 +1,705 @@ +// !$*UTF8*$! +{ + archiveVersion = 1; + classes = { + }; + objectVersion = 54; + objects = { + +/* Begin PBXAggregateTarget section */ + 33CC111A2044C6BA0003C045 /* Flutter Assemble */ = { + isa = PBXAggregateTarget; + buildConfigurationList = 33CC111B2044C6BA0003C045 /* Build configuration list for PBXAggregateTarget "Flutter Assemble" */; + buildPhases = ( + 33CC111E2044C6BF0003C045 /* ShellScript */, + ); + dependencies = ( + ); + name = "Flutter Assemble"; + productName = FLX; + }; +/* End PBXAggregateTarget section */ + +/* Begin PBXBuildFile section */ + 331C80D8294CF71000263BE5 /* RunnerTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 331C80D7294CF71000263BE5 /* RunnerTests.swift */; }; + 335BBD1B22A9A15E00E9071D /* GeneratedPluginRegistrant.swift in Sources */ = {isa = PBXBuildFile; fileRef = 335BBD1A22A9A15E00E9071D /* GeneratedPluginRegistrant.swift */; }; + 33CC10F12044A3C60003C045 /* AppDelegate.swift in Sources */ = {isa = PBXBuildFile; fileRef = 33CC10F02044A3C60003C045 /* AppDelegate.swift */; }; + 33CC10F32044A3C60003C045 /* Assets.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = 33CC10F22044A3C60003C045 /* Assets.xcassets */; }; + 33CC10F62044A3C60003C045 /* MainMenu.xib in Resources */ = {isa = PBXBuildFile; fileRef = 33CC10F42044A3C60003C045 /* MainMenu.xib */; }; + 33CC11132044BFA00003C045 /* MainFlutterWindow.swift in Sources */ = {isa = PBXBuildFile; fileRef = 33CC11122044BFA00003C045 /* MainFlutterWindow.swift */; }; +/* End PBXBuildFile section */ + +/* Begin PBXContainerItemProxy section */ + 331C80D9294CF71000263BE5 /* PBXContainerItemProxy */ = { + isa = PBXContainerItemProxy; + containerPortal = 33CC10E52044A3C60003C045 /* Project object */; + proxyType = 1; + remoteGlobalIDString = 33CC10EC2044A3C60003C045; + remoteInfo = Runner; + }; + 33CC111F2044C79F0003C045 /* PBXContainerItemProxy */ = { + isa = PBXContainerItemProxy; + containerPortal = 33CC10E52044A3C60003C045 /* Project object */; + proxyType = 1; + remoteGlobalIDString = 33CC111A2044C6BA0003C045; + remoteInfo = FLX; + }; +/* End PBXContainerItemProxy section */ + +/* Begin PBXCopyFilesBuildPhase section */ + 33CC110E2044A8840003C045 /* Bundle Framework */ = { + isa = PBXCopyFilesBuildPhase; + buildActionMask = 2147483647; + dstPath = ""; + dstSubfolderSpec = 10; + files = ( + ); + name = "Bundle Framework"; + runOnlyForDeploymentPostprocessing = 0; + }; +/* End PBXCopyFilesBuildPhase section */ + +/* Begin PBXFileReference section */ + 331C80D5294CF71000263BE5 /* RunnerTests.xctest */ = {isa = PBXFileReference; explicitFileType = wrapper.cfbundle; includeInIndex = 0; path = RunnerTests.xctest; sourceTree = BUILT_PRODUCTS_DIR; }; + 331C80D7294CF71000263BE5 /* RunnerTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = RunnerTests.swift; sourceTree = ""; }; + 333000ED22D3DE5D00554162 /* Warnings.xcconfig */ = {isa = PBXFileReference; lastKnownFileType = text.xcconfig; path = Warnings.xcconfig; sourceTree = ""; }; + 335BBD1A22A9A15E00E9071D /* GeneratedPluginRegistrant.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = GeneratedPluginRegistrant.swift; sourceTree = ""; }; + 33CC10ED2044A3C60003C045 /* premithus.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = "premithus.app"; sourceTree = BUILT_PRODUCTS_DIR; }; + 33CC10F02044A3C60003C045 /* AppDelegate.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AppDelegate.swift; sourceTree = ""; }; + 33CC10F22044A3C60003C045 /* Assets.xcassets */ = {isa = PBXFileReference; lastKnownFileType = folder.assetcatalog; name = Assets.xcassets; path = Runner/Assets.xcassets; sourceTree = ""; }; + 33CC10F52044A3C60003C045 /* Base */ = {isa = PBXFileReference; lastKnownFileType = file.xib; name = Base; path = Base.lproj/MainMenu.xib; sourceTree = ""; }; + 33CC10F72044A3C60003C045 /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; name = Info.plist; path = Runner/Info.plist; sourceTree = ""; }; + 33CC11122044BFA00003C045 /* MainFlutterWindow.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = MainFlutterWindow.swift; sourceTree = ""; }; + 33CEB47222A05771004F2AC0 /* Flutter-Debug.xcconfig */ = {isa = PBXFileReference; lastKnownFileType = text.xcconfig; path = "Flutter-Debug.xcconfig"; sourceTree = ""; }; + 33CEB47422A05771004F2AC0 /* Flutter-Release.xcconfig */ = {isa = PBXFileReference; lastKnownFileType = text.xcconfig; path = "Flutter-Release.xcconfig"; sourceTree = ""; }; + 33CEB47722A0578A004F2AC0 /* Flutter-Generated.xcconfig */ = {isa = PBXFileReference; lastKnownFileType = text.xcconfig; name = "Flutter-Generated.xcconfig"; path = "ephemeral/Flutter-Generated.xcconfig"; sourceTree = ""; }; + 33E51913231747F40026EE4D /* DebugProfile.entitlements */ = {isa = PBXFileReference; lastKnownFileType = text.plist.entitlements; path = DebugProfile.entitlements; sourceTree = ""; }; + 33E51914231749380026EE4D /* Release.entitlements */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.plist.entitlements; path = Release.entitlements; sourceTree = ""; }; + 33E5194F232828860026EE4D /* AppInfo.xcconfig */ = {isa = PBXFileReference; lastKnownFileType = text.xcconfig; path = AppInfo.xcconfig; sourceTree = ""; }; + 7AFA3C8E1D35360C0083082E /* Release.xcconfig */ = {isa = PBXFileReference; lastKnownFileType = text.xcconfig; path = Release.xcconfig; sourceTree = ""; }; + 9740EEB21CF90195004384FC /* Debug.xcconfig */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.xcconfig; path = Debug.xcconfig; sourceTree = ""; }; +/* End PBXFileReference section */ + +/* Begin PBXFrameworksBuildPhase section */ + 331C80D2294CF70F00263BE5 /* Frameworks */ = { + isa = PBXFrameworksBuildPhase; + buildActionMask = 2147483647; + files = ( + ); + runOnlyForDeploymentPostprocessing = 0; + }; + 33CC10EA2044A3C60003C045 /* Frameworks */ = { + isa = PBXFrameworksBuildPhase; + buildActionMask = 2147483647; + files = ( + ); + runOnlyForDeploymentPostprocessing = 0; + }; +/* End PBXFrameworksBuildPhase section */ + +/* Begin PBXGroup section */ + 331C80D6294CF71000263BE5 /* RunnerTests */ = { + isa = PBXGroup; + children = ( + 331C80D7294CF71000263BE5 /* RunnerTests.swift */, + ); + path = RunnerTests; + sourceTree = ""; + }; + 33BA886A226E78AF003329D5 /* Configs */ = { + isa = PBXGroup; + children = ( + 33E5194F232828860026EE4D /* AppInfo.xcconfig */, + 9740EEB21CF90195004384FC /* Debug.xcconfig */, + 7AFA3C8E1D35360C0083082E /* Release.xcconfig */, + 333000ED22D3DE5D00554162 /* Warnings.xcconfig */, + ); + path = Configs; + sourceTree = ""; + }; + 33CC10E42044A3C60003C045 = { + isa = PBXGroup; + children = ( + 33FAB671232836740065AC1E /* Runner */, + 33CEB47122A05771004F2AC0 /* Flutter */, + 331C80D6294CF71000263BE5 /* RunnerTests */, + 33CC10EE2044A3C60003C045 /* Products */, + D73912EC22F37F3D000D13A0 /* Frameworks */, + ); + sourceTree = ""; + }; + 33CC10EE2044A3C60003C045 /* Products */ = { + isa = PBXGroup; + children = ( + 33CC10ED2044A3C60003C045 /* premithus.app */, + 331C80D5294CF71000263BE5 /* RunnerTests.xctest */, + ); + name = Products; + sourceTree = ""; + }; + 33CC11242044D66E0003C045 /* Resources */ = { + isa = PBXGroup; + children = ( + 33CC10F22044A3C60003C045 /* Assets.xcassets */, + 33CC10F42044A3C60003C045 /* MainMenu.xib */, + 33CC10F72044A3C60003C045 /* Info.plist */, + ); + name = Resources; + path = ..; + sourceTree = ""; + }; + 33CEB47122A05771004F2AC0 /* Flutter */ = { + isa = PBXGroup; + children = ( + 335BBD1A22A9A15E00E9071D /* GeneratedPluginRegistrant.swift */, + 33CEB47222A05771004F2AC0 /* Flutter-Debug.xcconfig */, + 33CEB47422A05771004F2AC0 /* Flutter-Release.xcconfig */, + 33CEB47722A0578A004F2AC0 /* Flutter-Generated.xcconfig */, + ); + path = Flutter; + sourceTree = ""; + }; + 33FAB671232836740065AC1E /* Runner */ = { + isa = PBXGroup; + children = ( + 33CC10F02044A3C60003C045 /* AppDelegate.swift */, + 33CC11122044BFA00003C045 /* MainFlutterWindow.swift */, + 33E51913231747F40026EE4D /* DebugProfile.entitlements */, + 33E51914231749380026EE4D /* Release.entitlements */, + 33CC11242044D66E0003C045 /* Resources */, + 33BA886A226E78AF003329D5 /* Configs */, + ); + path = Runner; + sourceTree = ""; + }; + D73912EC22F37F3D000D13A0 /* Frameworks */ = { + isa = PBXGroup; + children = ( + ); + name = Frameworks; + sourceTree = ""; + }; +/* End PBXGroup section */ + +/* Begin PBXNativeTarget section */ + 331C80D4294CF70F00263BE5 /* RunnerTests */ = { + isa = PBXNativeTarget; + buildConfigurationList = 331C80DE294CF71000263BE5 /* Build configuration list for PBXNativeTarget "RunnerTests" */; + buildPhases = ( + 331C80D1294CF70F00263BE5 /* Sources */, + 331C80D2294CF70F00263BE5 /* Frameworks */, + 331C80D3294CF70F00263BE5 /* Resources */, + ); + buildRules = ( + ); + dependencies = ( + 331C80DA294CF71000263BE5 /* PBXTargetDependency */, + ); + name = RunnerTests; + productName = RunnerTests; + productReference = 331C80D5294CF71000263BE5 /* RunnerTests.xctest */; + productType = "com.apple.product-type.bundle.unit-test"; + }; + 33CC10EC2044A3C60003C045 /* Runner */ = { + isa = PBXNativeTarget; + buildConfigurationList = 33CC10FB2044A3C60003C045 /* Build configuration list for PBXNativeTarget "Runner" */; + buildPhases = ( + 33CC10E92044A3C60003C045 /* Sources */, + 33CC10EA2044A3C60003C045 /* Frameworks */, + 33CC10EB2044A3C60003C045 /* Resources */, + 33CC110E2044A8840003C045 /* Bundle Framework */, + 3399D490228B24CF009A79C7 /* ShellScript */, + ); + buildRules = ( + ); + dependencies = ( + 33CC11202044C79F0003C045 /* PBXTargetDependency */, + ); + name = Runner; + productName = Runner; + productReference = 33CC10ED2044A3C60003C045 /* premithus.app */; + productType = "com.apple.product-type.application"; + }; +/* End PBXNativeTarget section */ + +/* Begin PBXProject section */ + 33CC10E52044A3C60003C045 /* Project object */ = { + isa = PBXProject; + attributes = { + BuildIndependentTargetsInParallel = YES; + LastSwiftUpdateCheck = 0920; + LastUpgradeCheck = 1510; + ORGANIZATIONNAME = ""; + TargetAttributes = { + 331C80D4294CF70F00263BE5 = { + CreatedOnToolsVersion = 14.0; + TestTargetID = 33CC10EC2044A3C60003C045; + }; + 33CC10EC2044A3C60003C045 = { + CreatedOnToolsVersion = 9.2; + LastSwiftMigration = 1100; + ProvisioningStyle = Automatic; + SystemCapabilities = { + com.apple.Sandbox = { + enabled = 1; + }; + }; + }; + 33CC111A2044C6BA0003C045 = { + CreatedOnToolsVersion = 9.2; + ProvisioningStyle = Manual; + }; + }; + }; + buildConfigurationList = 33CC10E82044A3C60003C045 /* Build configuration list for PBXProject "Runner" */; + compatibilityVersion = "Xcode 9.3"; + developmentRegion = en; + hasScannedForEncodings = 0; + knownRegions = ( + en, + Base, + ); + mainGroup = 33CC10E42044A3C60003C045; + productRefGroup = 33CC10EE2044A3C60003C045 /* Products */; + projectDirPath = ""; + projectRoot = ""; + targets = ( + 33CC10EC2044A3C60003C045 /* Runner */, + 331C80D4294CF70F00263BE5 /* RunnerTests */, + 33CC111A2044C6BA0003C045 /* Flutter Assemble */, + ); + }; +/* End PBXProject section */ + +/* Begin PBXResourcesBuildPhase section */ + 331C80D3294CF70F00263BE5 /* Resources */ = { + isa = PBXResourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + ); + runOnlyForDeploymentPostprocessing = 0; + }; + 33CC10EB2044A3C60003C045 /* Resources */ = { + isa = PBXResourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + 33CC10F32044A3C60003C045 /* Assets.xcassets in Resources */, + 33CC10F62044A3C60003C045 /* MainMenu.xib in Resources */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; +/* End PBXResourcesBuildPhase section */ + +/* Begin PBXShellScriptBuildPhase section */ + 3399D490228B24CF009A79C7 /* ShellScript */ = { + isa = PBXShellScriptBuildPhase; + alwaysOutOfDate = 1; + buildActionMask = 2147483647; + files = ( + ); + inputFileListPaths = ( + ); + inputPaths = ( + ); + outputFileListPaths = ( + ); + outputPaths = ( + ); + runOnlyForDeploymentPostprocessing = 0; + shellPath = /bin/sh; + shellScript = "echo \"$PRODUCT_NAME.app\" > \"$PROJECT_DIR\"/Flutter/ephemeral/.app_filename && \"$FLUTTER_ROOT\"/packages/flutter_tools/bin/macos_assemble.sh embed\n"; + }; + 33CC111E2044C6BF0003C045 /* ShellScript */ = { + isa = PBXShellScriptBuildPhase; + buildActionMask = 2147483647; + files = ( + ); + inputFileListPaths = ( + Flutter/ephemeral/FlutterInputs.xcfilelist, + ); + inputPaths = ( + Flutter/ephemeral/tripwire, + ); + outputFileListPaths = ( + Flutter/ephemeral/FlutterOutputs.xcfilelist, + ); + outputPaths = ( + ); + runOnlyForDeploymentPostprocessing = 0; + shellPath = /bin/sh; + shellScript = "\"$FLUTTER_ROOT\"/packages/flutter_tools/bin/macos_assemble.sh && touch Flutter/ephemeral/tripwire"; + }; +/* End PBXShellScriptBuildPhase section */ + +/* Begin PBXSourcesBuildPhase section */ + 331C80D1294CF70F00263BE5 /* Sources */ = { + isa = PBXSourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + 331C80D8294CF71000263BE5 /* RunnerTests.swift in Sources */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; + 33CC10E92044A3C60003C045 /* Sources */ = { + isa = PBXSourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + 33CC11132044BFA00003C045 /* MainFlutterWindow.swift in Sources */, + 33CC10F12044A3C60003C045 /* AppDelegate.swift in Sources */, + 335BBD1B22A9A15E00E9071D /* GeneratedPluginRegistrant.swift in Sources */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; +/* End PBXSourcesBuildPhase section */ + +/* Begin PBXTargetDependency section */ + 331C80DA294CF71000263BE5 /* PBXTargetDependency */ = { + isa = PBXTargetDependency; + target = 33CC10EC2044A3C60003C045 /* Runner */; + targetProxy = 331C80D9294CF71000263BE5 /* PBXContainerItemProxy */; + }; + 33CC11202044C79F0003C045 /* PBXTargetDependency */ = { + isa = PBXTargetDependency; + target = 33CC111A2044C6BA0003C045 /* Flutter Assemble */; + targetProxy = 33CC111F2044C79F0003C045 /* PBXContainerItemProxy */; + }; +/* End PBXTargetDependency section */ + +/* Begin PBXVariantGroup section */ + 33CC10F42044A3C60003C045 /* MainMenu.xib */ = { + isa = PBXVariantGroup; + children = ( + 33CC10F52044A3C60003C045 /* Base */, + ); + name = MainMenu.xib; + path = Runner; + sourceTree = ""; + }; +/* End PBXVariantGroup section */ + +/* Begin XCBuildConfiguration section */ + 331C80DB294CF71000263BE5 /* Debug */ = { + isa = XCBuildConfiguration; + buildSettings = { + BUNDLE_LOADER = "$(TEST_HOST)"; + CURRENT_PROJECT_VERSION = 1; + GENERATE_INFOPLIST_FILE = YES; + MARKETING_VERSION = 1.0; + PRODUCT_BUNDLE_IDENTIFIER = in.inmodel.premithus.RunnerTests; + PRODUCT_NAME = "$(TARGET_NAME)"; + SWIFT_VERSION = 5.0; + TEST_HOST = "$(BUILT_PRODUCTS_DIR)/premithus.app/$(BUNDLE_EXECUTABLE_FOLDER_PATH)/premithus"; + }; + name = Debug; + }; + 331C80DC294CF71000263BE5 /* Release */ = { + isa = XCBuildConfiguration; + buildSettings = { + BUNDLE_LOADER = "$(TEST_HOST)"; + CURRENT_PROJECT_VERSION = 1; + GENERATE_INFOPLIST_FILE = YES; + MARKETING_VERSION = 1.0; + PRODUCT_BUNDLE_IDENTIFIER = in.inmodel.premithus.RunnerTests; + PRODUCT_NAME = "$(TARGET_NAME)"; + SWIFT_VERSION = 5.0; + TEST_HOST = "$(BUILT_PRODUCTS_DIR)/premithus.app/$(BUNDLE_EXECUTABLE_FOLDER_PATH)/premithus"; + }; + name = Release; + }; + 331C80DD294CF71000263BE5 /* Profile */ = { + isa = XCBuildConfiguration; + buildSettings = { + BUNDLE_LOADER = "$(TEST_HOST)"; + CURRENT_PROJECT_VERSION = 1; + GENERATE_INFOPLIST_FILE = YES; + MARKETING_VERSION = 1.0; + PRODUCT_BUNDLE_IDENTIFIER = in.inmodel.premithus.RunnerTests; + PRODUCT_NAME = "$(TARGET_NAME)"; + SWIFT_VERSION = 5.0; + TEST_HOST = "$(BUILT_PRODUCTS_DIR)/premithus.app/$(BUNDLE_EXECUTABLE_FOLDER_PATH)/premithus"; + }; + name = Profile; + }; + 338D0CE9231458BD00FA5F75 /* Profile */ = { + isa = XCBuildConfiguration; + baseConfigurationReference = 7AFA3C8E1D35360C0083082E /* Release.xcconfig */; + buildSettings = { + ALWAYS_SEARCH_USER_PATHS = NO; + ASSETCATALOG_COMPILER_GENERATE_SWIFT_ASSET_SYMBOL_EXTENSIONS = YES; + CLANG_ANALYZER_NONNULL = YES; + CLANG_ANALYZER_NUMBER_OBJECT_CONVERSION = YES_AGGRESSIVE; + CLANG_CXX_LANGUAGE_STANDARD = "gnu++14"; + CLANG_CXX_LIBRARY = "libc++"; + CLANG_ENABLE_MODULES = YES; + CLANG_ENABLE_OBJC_ARC = YES; + CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES; + CLANG_WARN_BOOL_CONVERSION = YES; + CLANG_WARN_CONSTANT_CONVERSION = YES; + CLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES; + CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; + CLANG_WARN_DOCUMENTATION_COMMENTS = YES; + CLANG_WARN_EMPTY_BODY = YES; + CLANG_WARN_ENUM_CONVERSION = YES; + CLANG_WARN_INFINITE_RECURSION = YES; + CLANG_WARN_INT_CONVERSION = YES; + CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES; + CLANG_WARN_OBJC_LITERAL_CONVERSION = YES; + CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; + CLANG_WARN_RANGE_LOOP_ANALYSIS = YES; + CLANG_WARN_SUSPICIOUS_MOVE = YES; + CODE_SIGN_IDENTITY = "-"; + COPY_PHASE_STRIP = NO; + DEAD_CODE_STRIPPING = YES; + DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym"; + ENABLE_NS_ASSERTIONS = NO; + ENABLE_STRICT_OBJC_MSGSEND = YES; + ENABLE_USER_SCRIPT_SANDBOXING = NO; + GCC_C_LANGUAGE_STANDARD = gnu11; + GCC_NO_COMMON_BLOCKS = YES; + GCC_WARN_64_TO_32_BIT_CONVERSION = YES; + GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; + GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; + GCC_WARN_UNUSED_FUNCTION = YES; + GCC_WARN_UNUSED_VARIABLE = YES; + MACOSX_DEPLOYMENT_TARGET = 10.15; + MTL_ENABLE_DEBUG_INFO = NO; + SDKROOT = macosx; + SWIFT_COMPILATION_MODE = wholemodule; + SWIFT_OPTIMIZATION_LEVEL = "-O"; + }; + name = Profile; + }; + 338D0CEA231458BD00FA5F75 /* Profile */ = { + isa = XCBuildConfiguration; + baseConfigurationReference = 33E5194F232828860026EE4D /* AppInfo.xcconfig */; + buildSettings = { + ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; + CLANG_ENABLE_MODULES = YES; + CODE_SIGN_ENTITLEMENTS = Runner/DebugProfile.entitlements; + CODE_SIGN_STYLE = Automatic; + COMBINE_HIDPI_IMAGES = YES; + INFOPLIST_FILE = Runner/Info.plist; + LD_RUNPATH_SEARCH_PATHS = ( + "$(inherited)", + "@executable_path/../Frameworks", + ); + PROVISIONING_PROFILE_SPECIFIER = ""; + SWIFT_VERSION = 5.0; + }; + name = Profile; + }; + 338D0CEB231458BD00FA5F75 /* Profile */ = { + isa = XCBuildConfiguration; + buildSettings = { + CODE_SIGN_STYLE = Manual; + PRODUCT_NAME = "$(TARGET_NAME)"; + }; + name = Profile; + }; + 33CC10F92044A3C60003C045 /* Debug */ = { + isa = XCBuildConfiguration; + baseConfigurationReference = 9740EEB21CF90195004384FC /* Debug.xcconfig */; + buildSettings = { + ALWAYS_SEARCH_USER_PATHS = NO; + ASSETCATALOG_COMPILER_GENERATE_SWIFT_ASSET_SYMBOL_EXTENSIONS = YES; + CLANG_ANALYZER_NONNULL = YES; + CLANG_ANALYZER_NUMBER_OBJECT_CONVERSION = YES_AGGRESSIVE; + CLANG_CXX_LANGUAGE_STANDARD = "gnu++14"; + CLANG_CXX_LIBRARY = "libc++"; + CLANG_ENABLE_MODULES = YES; + CLANG_ENABLE_OBJC_ARC = YES; + CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES; + CLANG_WARN_BOOL_CONVERSION = YES; + CLANG_WARN_CONSTANT_CONVERSION = YES; + CLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES; + CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; + CLANG_WARN_DOCUMENTATION_COMMENTS = YES; + CLANG_WARN_EMPTY_BODY = YES; + CLANG_WARN_ENUM_CONVERSION = YES; + CLANG_WARN_INFINITE_RECURSION = YES; + CLANG_WARN_INT_CONVERSION = YES; + CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES; + CLANG_WARN_OBJC_LITERAL_CONVERSION = YES; + CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; + CLANG_WARN_RANGE_LOOP_ANALYSIS = YES; + CLANG_WARN_SUSPICIOUS_MOVE = YES; + CODE_SIGN_IDENTITY = "-"; + COPY_PHASE_STRIP = NO; + DEAD_CODE_STRIPPING = YES; + DEBUG_INFORMATION_FORMAT = dwarf; + ENABLE_STRICT_OBJC_MSGSEND = YES; + ENABLE_TESTABILITY = YES; + ENABLE_USER_SCRIPT_SANDBOXING = NO; + GCC_C_LANGUAGE_STANDARD = gnu11; + GCC_DYNAMIC_NO_PIC = NO; + GCC_NO_COMMON_BLOCKS = YES; + GCC_OPTIMIZATION_LEVEL = 0; + GCC_PREPROCESSOR_DEFINITIONS = ( + "DEBUG=1", + "$(inherited)", + ); + GCC_WARN_64_TO_32_BIT_CONVERSION = YES; + GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; + GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; + GCC_WARN_UNUSED_FUNCTION = YES; + GCC_WARN_UNUSED_VARIABLE = YES; + MACOSX_DEPLOYMENT_TARGET = 10.15; + MTL_ENABLE_DEBUG_INFO = YES; + ONLY_ACTIVE_ARCH = YES; + SDKROOT = macosx; + SWIFT_ACTIVE_COMPILATION_CONDITIONS = DEBUG; + SWIFT_OPTIMIZATION_LEVEL = "-Onone"; + }; + name = Debug; + }; + 33CC10FA2044A3C60003C045 /* Release */ = { + isa = XCBuildConfiguration; + baseConfigurationReference = 7AFA3C8E1D35360C0083082E /* Release.xcconfig */; + buildSettings = { + ALWAYS_SEARCH_USER_PATHS = NO; + ASSETCATALOG_COMPILER_GENERATE_SWIFT_ASSET_SYMBOL_EXTENSIONS = YES; + CLANG_ANALYZER_NONNULL = YES; + CLANG_ANALYZER_NUMBER_OBJECT_CONVERSION = YES_AGGRESSIVE; + CLANG_CXX_LANGUAGE_STANDARD = "gnu++14"; + CLANG_CXX_LIBRARY = "libc++"; + CLANG_ENABLE_MODULES = YES; + CLANG_ENABLE_OBJC_ARC = YES; + CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES; + CLANG_WARN_BOOL_CONVERSION = YES; + CLANG_WARN_CONSTANT_CONVERSION = YES; + CLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES; + CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; + CLANG_WARN_DOCUMENTATION_COMMENTS = YES; + CLANG_WARN_EMPTY_BODY = YES; + CLANG_WARN_ENUM_CONVERSION = YES; + CLANG_WARN_INFINITE_RECURSION = YES; + CLANG_WARN_INT_CONVERSION = YES; + CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES; + CLANG_WARN_OBJC_LITERAL_CONVERSION = YES; + CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; + CLANG_WARN_RANGE_LOOP_ANALYSIS = YES; + CLANG_WARN_SUSPICIOUS_MOVE = YES; + CODE_SIGN_IDENTITY = "-"; + COPY_PHASE_STRIP = NO; + DEAD_CODE_STRIPPING = YES; + DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym"; + ENABLE_NS_ASSERTIONS = NO; + ENABLE_STRICT_OBJC_MSGSEND = YES; + ENABLE_USER_SCRIPT_SANDBOXING = NO; + GCC_C_LANGUAGE_STANDARD = gnu11; + GCC_NO_COMMON_BLOCKS = YES; + GCC_WARN_64_TO_32_BIT_CONVERSION = YES; + GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; + GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; + GCC_WARN_UNUSED_FUNCTION = YES; + GCC_WARN_UNUSED_VARIABLE = YES; + MACOSX_DEPLOYMENT_TARGET = 10.15; + MTL_ENABLE_DEBUG_INFO = NO; + SDKROOT = macosx; + SWIFT_COMPILATION_MODE = wholemodule; + SWIFT_OPTIMIZATION_LEVEL = "-O"; + }; + name = Release; + }; + 33CC10FC2044A3C60003C045 /* Debug */ = { + isa = XCBuildConfiguration; + baseConfigurationReference = 33E5194F232828860026EE4D /* AppInfo.xcconfig */; + buildSettings = { + ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; + CLANG_ENABLE_MODULES = YES; + CODE_SIGN_ENTITLEMENTS = Runner/DebugProfile.entitlements; + CODE_SIGN_STYLE = Automatic; + COMBINE_HIDPI_IMAGES = YES; + INFOPLIST_FILE = Runner/Info.plist; + LD_RUNPATH_SEARCH_PATHS = ( + "$(inherited)", + "@executable_path/../Frameworks", + ); + PROVISIONING_PROFILE_SPECIFIER = ""; + SWIFT_OPTIMIZATION_LEVEL = "-Onone"; + SWIFT_VERSION = 5.0; + }; + name = Debug; + }; + 33CC10FD2044A3C60003C045 /* Release */ = { + isa = XCBuildConfiguration; + baseConfigurationReference = 33E5194F232828860026EE4D /* AppInfo.xcconfig */; + buildSettings = { + ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; + CLANG_ENABLE_MODULES = YES; + CODE_SIGN_ENTITLEMENTS = Runner/Release.entitlements; + CODE_SIGN_STYLE = Automatic; + COMBINE_HIDPI_IMAGES = YES; + INFOPLIST_FILE = Runner/Info.plist; + LD_RUNPATH_SEARCH_PATHS = ( + "$(inherited)", + "@executable_path/../Frameworks", + ); + PROVISIONING_PROFILE_SPECIFIER = ""; + SWIFT_VERSION = 5.0; + }; + name = Release; + }; + 33CC111C2044C6BA0003C045 /* Debug */ = { + isa = XCBuildConfiguration; + buildSettings = { + CODE_SIGN_STYLE = Manual; + PRODUCT_NAME = "$(TARGET_NAME)"; + }; + name = Debug; + }; + 33CC111D2044C6BA0003C045 /* Release */ = { + isa = XCBuildConfiguration; + buildSettings = { + CODE_SIGN_STYLE = Automatic; + PRODUCT_NAME = "$(TARGET_NAME)"; + }; + name = Release; + }; +/* End XCBuildConfiguration section */ + +/* Begin XCConfigurationList section */ + 331C80DE294CF71000263BE5 /* Build configuration list for PBXNativeTarget "RunnerTests" */ = { + isa = XCConfigurationList; + buildConfigurations = ( + 331C80DB294CF71000263BE5 /* Debug */, + 331C80DC294CF71000263BE5 /* Release */, + 331C80DD294CF71000263BE5 /* Profile */, + ); + defaultConfigurationIsVisible = 0; + defaultConfigurationName = Release; + }; + 33CC10E82044A3C60003C045 /* Build configuration list for PBXProject "Runner" */ = { + isa = XCConfigurationList; + buildConfigurations = ( + 33CC10F92044A3C60003C045 /* Debug */, + 33CC10FA2044A3C60003C045 /* Release */, + 338D0CE9231458BD00FA5F75 /* Profile */, + ); + defaultConfigurationIsVisible = 0; + defaultConfigurationName = Release; + }; + 33CC10FB2044A3C60003C045 /* Build configuration list for PBXNativeTarget "Runner" */ = { + isa = XCConfigurationList; + buildConfigurations = ( + 33CC10FC2044A3C60003C045 /* Debug */, + 33CC10FD2044A3C60003C045 /* Release */, + 338D0CEA231458BD00FA5F75 /* Profile */, + ); + defaultConfigurationIsVisible = 0; + defaultConfigurationName = Release; + }; + 33CC111B2044C6BA0003C045 /* Build configuration list for PBXAggregateTarget "Flutter Assemble" */ = { + isa = XCConfigurationList; + buildConfigurations = ( + 33CC111C2044C6BA0003C045 /* Debug */, + 33CC111D2044C6BA0003C045 /* Release */, + 338D0CEB231458BD00FA5F75 /* Profile */, + ); + defaultConfigurationIsVisible = 0; + defaultConfigurationName = Release; + }; +/* End XCConfigurationList section */ + }; + rootObject = 33CC10E52044A3C60003C045 /* Project object */; +} diff --git a/macos/Runner.xcodeproj/project.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist b/macos/Runner.xcodeproj/project.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist new file mode 100644 index 0000000000000000000000000000000000000000..18d981003d68d0546c4804ac2ff47dd97c6e7921 --- /dev/null +++ b/macos/Runner.xcodeproj/project.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist @@ -0,0 +1,8 @@ + + + + + IDEDidComputeMac32BitWarning + + + diff --git a/macos/Runner.xcodeproj/xcshareddata/xcschemes/Runner.xcscheme b/macos/Runner.xcodeproj/xcshareddata/xcschemes/Runner.xcscheme new file mode 100644 index 0000000000000000000000000000000000000000..f2d0bf988e9c2fb8739ca3f66f32cd477996a23e --- /dev/null +++ b/macos/Runner.xcodeproj/xcshareddata/xcschemes/Runner.xcscheme @@ -0,0 +1,99 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/macos/Runner.xcworkspace/contents.xcworkspacedata b/macos/Runner.xcworkspace/contents.xcworkspacedata new file mode 100644 index 0000000000000000000000000000000000000000..1d526a16ed0f1cd0c2409d848bf489b93fefa3b2 --- /dev/null +++ b/macos/Runner.xcworkspace/contents.xcworkspacedata @@ -0,0 +1,7 @@ + + + + + diff --git a/macos/Runner.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist b/macos/Runner.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist new file mode 100644 index 0000000000000000000000000000000000000000..18d981003d68d0546c4804ac2ff47dd97c6e7921 --- /dev/null +++ b/macos/Runner.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist @@ -0,0 +1,8 @@ + + + + + IDEDidComputeMac32BitWarning + + + diff --git a/macos/Runner/AppDelegate.swift b/macos/Runner/AppDelegate.swift new file mode 100644 index 0000000000000000000000000000000000000000..b3c176141221dbe2b40d3e36942b15068ba48677 --- /dev/null +++ b/macos/Runner/AppDelegate.swift @@ -0,0 +1,13 @@ +import Cocoa +import FlutterMacOS + +@main +class AppDelegate: FlutterAppDelegate { + override func applicationShouldTerminateAfterLastWindowClosed(_ sender: NSApplication) -> Bool { + return true + } + + override func applicationSupportsSecureRestorableState(_ app: NSApplication) -> Bool { + return true + } +} diff --git a/macos/Runner/Assets.xcassets/AppIcon.appiconset/Contents.json b/macos/Runner/Assets.xcassets/AppIcon.appiconset/Contents.json new file mode 100644 index 0000000000000000000000000000000000000000..a2ec33f19f110ebff51a23342d7bc29ec9a1aaa6 --- /dev/null +++ b/macos/Runner/Assets.xcassets/AppIcon.appiconset/Contents.json @@ -0,0 +1,68 @@ +{ + "images" : [ + { + "size" : "16x16", + "idiom" : "mac", + "filename" : "app_icon_16.png", + "scale" : "1x" + }, + { + "size" : "16x16", + "idiom" : "mac", + "filename" : "app_icon_32.png", + "scale" : "2x" + }, + { + "size" : "32x32", + "idiom" : "mac", + "filename" : "app_icon_32.png", + "scale" : "1x" + }, + { + "size" : "32x32", + "idiom" : "mac", + "filename" : "app_icon_64.png", + "scale" : "2x" + }, + { + "size" : "128x128", + "idiom" : "mac", + "filename" : "app_icon_128.png", + "scale" : "1x" + }, + { + "size" : "128x128", + "idiom" : "mac", + "filename" : "app_icon_256.png", + "scale" : "2x" + }, + { + "size" : "256x256", + "idiom" : "mac", + "filename" : "app_icon_256.png", + "scale" : "1x" + }, + { + "size" : "256x256", + "idiom" : "mac", + "filename" : "app_icon_512.png", + "scale" : "2x" + }, + { + "size" : "512x512", + "idiom" : "mac", + "filename" : "app_icon_512.png", + "scale" : "1x" + }, + { + "size" : "512x512", + "idiom" : "mac", + "filename" : "app_icon_1024.png", + "scale" : "2x" + } + ], + "info" : { + "version" : 1, + "author" : "xcode" + } +} diff --git a/macos/Runner/Base.lproj/MainMenu.xib b/macos/Runner/Base.lproj/MainMenu.xib new file mode 100644 index 0000000000000000000000000000000000000000..80e867a4e06b4dc26d0a2b327cbd54041addc50a --- /dev/null +++ b/macos/Runner/Base.lproj/MainMenu.xib @@ -0,0 +1,343 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/macos/Runner/Configs/AppInfo.xcconfig b/macos/Runner/Configs/AppInfo.xcconfig new file mode 100644 index 0000000000000000000000000000000000000000..6226b349657e3ed302a539b0aa99941bd8a996eb --- /dev/null +++ b/macos/Runner/Configs/AppInfo.xcconfig @@ -0,0 +1,14 @@ +// Application-level settings for the Runner target. +// +// This may be replaced with something auto-generated from metadata (e.g., pubspec.yaml) in the +// future. If not, the values below would default to using the project name when this becomes a +// 'flutter create' template. + +// The application's name. By default this is also the title of the Flutter window. +PRODUCT_NAME = premithus + +// The application's bundle identifier +PRODUCT_BUNDLE_IDENTIFIER = in.inmodel.premithus + +// The copyright displayed in application information +PRODUCT_COPYRIGHT = Copyright © 2026 in.inmodel. All rights reserved. diff --git a/macos/Runner/Configs/Debug.xcconfig b/macos/Runner/Configs/Debug.xcconfig new file mode 100644 index 0000000000000000000000000000000000000000..36b0fd9464f45b33f482e64bea579787e142affa --- /dev/null +++ b/macos/Runner/Configs/Debug.xcconfig @@ -0,0 +1,2 @@ +#include "../../Flutter/Flutter-Debug.xcconfig" +#include "Warnings.xcconfig" diff --git a/macos/Runner/Configs/Release.xcconfig b/macos/Runner/Configs/Release.xcconfig new file mode 100644 index 0000000000000000000000000000000000000000..dff4f49561c816f70eaea557d889d31cf63447ac --- /dev/null +++ b/macos/Runner/Configs/Release.xcconfig @@ -0,0 +1,2 @@ +#include "../../Flutter/Flutter-Release.xcconfig" +#include "Warnings.xcconfig" diff --git a/macos/Runner/Configs/Warnings.xcconfig b/macos/Runner/Configs/Warnings.xcconfig new file mode 100644 index 0000000000000000000000000000000000000000..42bcbf4780b187e80025b7917058bcb882012aa1 --- /dev/null +++ b/macos/Runner/Configs/Warnings.xcconfig @@ -0,0 +1,13 @@ +WARNING_CFLAGS = -Wall -Wconditional-uninitialized -Wnullable-to-nonnull-conversion -Wmissing-method-return-type -Woverlength-strings +GCC_WARN_UNDECLARED_SELECTOR = YES +CLANG_UNDEFINED_BEHAVIOR_SANITIZER_NULLABILITY = YES +CLANG_WARN_UNGUARDED_AVAILABILITY = YES_AGGRESSIVE +CLANG_WARN__DUPLICATE_METHOD_MATCH = YES +CLANG_WARN_PRAGMA_PACK = YES +CLANG_WARN_STRICT_PROTOTYPES = YES +CLANG_WARN_COMMA = YES +GCC_WARN_STRICT_SELECTOR_MATCH = YES +CLANG_WARN_OBJC_REPEATED_USE_OF_WEAK = YES +CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = YES +GCC_WARN_SHADOW = YES +CLANG_WARN_UNREACHABLE_CODE = YES diff --git a/macos/Runner/DebugProfile.entitlements b/macos/Runner/DebugProfile.entitlements new file mode 100644 index 0000000000000000000000000000000000000000..dddb8a30c851e7ef5b16a9108934bd1217b6b43f --- /dev/null +++ b/macos/Runner/DebugProfile.entitlements @@ -0,0 +1,12 @@ + + + + + com.apple.security.app-sandbox + + com.apple.security.cs.allow-jit + + com.apple.security.network.server + + + diff --git a/macos/Runner/Info.plist b/macos/Runner/Info.plist new file mode 100644 index 0000000000000000000000000000000000000000..4789daa6a443eefa7f3f729164a18351e06e9800 --- /dev/null +++ b/macos/Runner/Info.plist @@ -0,0 +1,32 @@ + + + + + CFBundleDevelopmentRegion + $(DEVELOPMENT_LANGUAGE) + CFBundleExecutable + $(EXECUTABLE_NAME) + CFBundleIconFile + + CFBundleIdentifier + $(PRODUCT_BUNDLE_IDENTIFIER) + CFBundleInfoDictionaryVersion + 6.0 + CFBundleName + $(PRODUCT_NAME) + CFBundlePackageType + APPL + CFBundleShortVersionString + $(FLUTTER_BUILD_NAME) + CFBundleVersion + $(FLUTTER_BUILD_NUMBER) + LSMinimumSystemVersion + $(MACOSX_DEPLOYMENT_TARGET) + NSHumanReadableCopyright + $(PRODUCT_COPYRIGHT) + NSMainNibFile + MainMenu + NSPrincipalClass + NSApplication + + diff --git a/macos/Runner/MainFlutterWindow.swift b/macos/Runner/MainFlutterWindow.swift new file mode 100644 index 0000000000000000000000000000000000000000..3cc05eb23491684aae1c51ce94668a142bad5125 --- /dev/null +++ b/macos/Runner/MainFlutterWindow.swift @@ -0,0 +1,15 @@ +import Cocoa +import FlutterMacOS + +class MainFlutterWindow: NSWindow { + override func awakeFromNib() { + let flutterViewController = FlutterViewController() + let windowFrame = self.frame + self.contentViewController = flutterViewController + self.setFrame(windowFrame, display: true) + + RegisterGeneratedPlugins(registry: flutterViewController) + + super.awakeFromNib() + } +} diff --git a/macos/Runner/Release.entitlements b/macos/Runner/Release.entitlements new file mode 100644 index 0000000000000000000000000000000000000000..852fa1a4728ae4789e3bca55dd07caef3b41f2a5 --- /dev/null +++ b/macos/Runner/Release.entitlements @@ -0,0 +1,8 @@ + + + + + com.apple.security.app-sandbox + + + diff --git a/macos/RunnerTests/RunnerTests.swift b/macos/RunnerTests/RunnerTests.swift new file mode 100644 index 0000000000000000000000000000000000000000..61f3bd1fc504c3b78271416d8cfd14faa1dae2b4 --- /dev/null +++ b/macos/RunnerTests/RunnerTests.swift @@ -0,0 +1,12 @@ +import Cocoa +import FlutterMacOS +import XCTest + +class RunnerTests: XCTestCase { + + func testExample() { + // If you add code to the Runner application, consider adding tests here. + // See https://developer.apple.com/documentation/xctest for more information about using XCTest. + } + +} diff --git a/pubspec.lock b/pubspec.lock new file mode 100644 index 0000000000000000000000000000000000000000..493c54cc2e33a64f02db12816f8929f954f8e59a --- /dev/null +++ b/pubspec.lock @@ -0,0 +1,658 @@ +# Generated by pub +# See https://dart.dev/tools/pub/glossary#lockfile +packages: + async: + dependency: transitive + description: + name: async + sha256: "758e6d74e971c3e5aceb4110bfd6698efc7f501675bcfe0c775459a8140750eb" + url: "https://pub.dev" + source: hosted + version: "2.13.0" + boolean_selector: + dependency: transitive + description: + name: boolean_selector + sha256: "8aab1771e1243a5063b8b0ff68042d67334e3feab9e95b9490f9a6ebf73b42ea" + url: "https://pub.dev" + source: hosted + version: "2.1.2" + characters: + dependency: transitive + description: + name: characters + sha256: faf38497bda5ead2a8c7615f4f7939df04333478bf32e4173fcb06d428b5716b + url: "https://pub.dev" + source: hosted + version: "1.4.1" + clock: + dependency: transitive + description: + name: clock + sha256: fddb70d9b5277016c77a80201021d40a2247104d9f4aa7bab7157b7e3f05b84b + 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" + collection: + dependency: transitive + description: + name: collection + sha256: "2f5709ae4d3d59dd8f7cd309b4e023046b57d8a6c82130785d2b0e5868084e76" + url: "https://pub.dev" + source: hosted + version: "1.19.1" + crypto: + dependency: transitive + description: + name: crypto + sha256: c8ea0233063ba03258fbcf2ca4d6dadfefe14f02fab57702265467a19f27fadf + url: "https://pub.dev" + source: hosted + version: "3.0.7" + cupertino_icons: + dependency: "direct main" + description: + name: cupertino_icons + sha256: ba631d1c7f7bef6b729a622b7b752645a2d076dba9976925b8f25725a30e1ee6 + url: "https://pub.dev" + source: hosted + version: "1.0.8" + fake_async: + dependency: transitive + description: + name: fake_async + sha256: "5368f224a74523e8d2e7399ea1638b37aecfca824a3cc4dfdf77bf1fa905ac44" + 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" + flutter: + dependency: "direct main" + description: flutter + source: sdk + version: "0.0.0" + flutter_animate: + dependency: "direct main" + description: + name: flutter_animate + sha256: "7befe2d3252728afb77aecaaea1dec88a89d35b9b1d2eea6d04479e8af9117b5" + url: "https://pub.dev" + source: hosted + version: "4.5.2" + flutter_keyboard_visibility: + dependency: "direct main" + description: + name: flutter_keyboard_visibility + sha256: "98664be7be0e3ffca00de50f7f6a287ab62c763fc8c762e0a21584584a3ff4f8" + url: "https://pub.dev" + source: hosted + version: "6.0.0" + flutter_keyboard_visibility_linux: + dependency: transitive + description: + name: flutter_keyboard_visibility_linux + sha256: "6fba7cd9bb033b6ddd8c2beb4c99ad02d728f1e6e6d9b9446667398b2ac39f08" + url: "https://pub.dev" + source: hosted + version: "1.0.0" + flutter_keyboard_visibility_macos: + dependency: transitive + description: + name: flutter_keyboard_visibility_macos + sha256: c5c49b16fff453dfdafdc16f26bdd8fb8d55812a1d50b0ce25fc8d9f2e53d086 + url: "https://pub.dev" + source: hosted + version: "1.0.0" + flutter_keyboard_visibility_platform_interface: + dependency: transitive + description: + name: flutter_keyboard_visibility_platform_interface + sha256: e43a89845873f7be10cb3884345ceb9aebf00a659f479d1c8f4293fcb37022a4 + url: "https://pub.dev" + source: hosted + version: "2.0.0" + flutter_keyboard_visibility_web: + dependency: transitive + description: + name: flutter_keyboard_visibility_web + sha256: d3771a2e752880c79203f8d80658401d0c998e4183edca05a149f5098ce6e3d1 + url: "https://pub.dev" + source: hosted + version: "2.0.0" + flutter_keyboard_visibility_windows: + dependency: transitive + description: + name: flutter_keyboard_visibility_windows + sha256: fc4b0f0b6be9b93ae527f3d527fb56ee2d918cd88bbca438c478af7bcfd0ef73 + url: "https://pub.dev" + source: hosted + version: "1.0.0" + flutter_lints: + dependency: "direct dev" + description: + name: flutter_lints + sha256: "3105dc8492f6183fb076ccf1f351ac3d60564bff92e20bfc4af9cc1651f4e7e1" + url: "https://pub.dev" + source: hosted + version: "6.0.0" + flutter_shaders: + dependency: transitive + description: + name: flutter_shaders + sha256: "34794acadd8275d971e02df03afee3dee0f98dbfb8c4837082ad0034f612a3e2" + url: "https://pub.dev" + source: hosted + version: "0.1.3" + 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" + gap: + dependency: "direct main" + description: + name: gap + sha256: f19387d4e32f849394758b91377f9153a1b41d79513ef7668c088c77dbc6955d + url: "https://pub.dev" + source: hosted + version: "3.0.1" + glob: + dependency: transitive + description: + name: glob + sha256: c3f1ee72c96f8f78935e18aa8cecced9ab132419e8625dc187e1c2408efc20de + url: "https://pub.dev" + source: hosted + version: "2.1.3" + google_fonts: + dependency: "direct main" + description: + name: google_fonts + sha256: ba03d03bcaa2f6cb7bd920e3b5027181db75ab524f8891c8bc3aa603885b8055 + url: "https://pub.dev" + source: hosted + version: "6.3.3" + 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_parser: + dependency: transitive + description: + name: http_parser + sha256: "178d74305e7866013777bab2c3d8726205dc5a4dd935297175b19a23a2e66571" + url: "https://pub.dev" + source: hosted + version: "4.1.2" + languagetool_textfield: + dependency: "direct main" + description: + name: languagetool_textfield + sha256: "53ae4016e0544daadae3594cb4a55e2c40fc3d533b6a64df9d0df1ede55c4437" + url: "https://pub.dev" + source: hosted + version: "0.1.1" + leak_tracker: + dependency: transitive + description: + name: leak_tracker + sha256: "33e2e26bdd85a0112ec15400c8cbffea70d0f9c3407491f672a2fad47915e2de" + url: "https://pub.dev" + source: hosted + version: "11.0.2" + leak_tracker_flutter_testing: + dependency: transitive + description: + name: leak_tracker_flutter_testing + sha256: "1dbc140bb5a23c75ea9c4811222756104fbcd1a27173f0c34ca01e16bea473c1" + url: "https://pub.dev" + source: hosted + version: "3.0.10" + leak_tracker_testing: + dependency: transitive + description: + name: leak_tracker_testing + sha256: "8d5a2d49f4a66b49744b23b018848400d23e54caf9463f4eb20df3eb8acb2eb1" + url: "https://pub.dev" + source: hosted + version: "3.0.2" + lints: + dependency: transitive + description: + name: lints + sha256: "12f842a479589fea194fe5c5a3095abc7be0c1f2ddfa9a0e76aed1dbd26a87df" + url: "https://pub.dev" + source: hosted + version: "6.1.0" + logging: + dependency: transitive + description: + name: logging + sha256: c8245ada5f1717ed44271ed1c26b8ce85ca3228fd2ffdb75468ab01979309d61 + url: "https://pub.dev" + source: hosted + version: "1.3.0" + matcher: + dependency: transitive + description: + name: matcher + sha256: dc0b7dc7651697ea4ff3e69ef44b0407ea32c487a39fff6a4004fa585e901861 + url: "https://pub.dev" + source: hosted + version: "0.12.19" + material_color_utilities: + dependency: transitive + description: + name: material_color_utilities + sha256: "9c337007e82b1889149c82ed242ed1cb24a66044e30979c44912381e9be4c48b" + url: "https://pub.dev" + source: hosted + version: "0.13.0" + meta: + dependency: transitive + description: + name: meta + sha256: "23f08335362185a5ea2ad3a4e597f1375e78bce8a040df5c600c8d3552ef2394" + url: "https://pub.dev" + source: hosted + version: "1.17.0" + 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" + path: + dependency: "direct main" + description: + name: path + sha256: "75cca69d1490965be98c73ceaea117e8a04dd21217b37b292c9ddbec0d955bc5" + url: "https://pub.dev" + source: hosted + version: "1.9.1" + path_provider: + dependency: "direct main" + 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" + permission_handler: + dependency: "direct main" + description: + name: permission_handler + sha256: "59adad729136f01ea9e35a48f5d1395e25cba6cea552249ddbe9cf950f5d7849" + url: "https://pub.dev" + source: hosted + version: "11.4.0" + permission_handler_android: + dependency: transitive + description: + name: permission_handler_android + sha256: d3971dcdd76182a0c198c096b5db2f0884b0d4196723d21a866fc4cdea057ebc + url: "https://pub.dev" + source: hosted + version: "12.1.0" + permission_handler_apple: + dependency: transitive + description: + name: permission_handler_apple + sha256: f000131e755c54cf4d84a5d8bd6e4149e262cc31c5a8b1d698de1ac85fa41023 + url: "https://pub.dev" + source: hosted + version: "9.4.7" + permission_handler_html: + dependency: transitive + description: + name: permission_handler_html + sha256: "38f000e83355abb3392140f6bc3030660cfaef189e1f87824facb76300b4ff24" + url: "https://pub.dev" + source: hosted + version: "0.1.3+5" + permission_handler_platform_interface: + dependency: transitive + description: + name: permission_handler_platform_interface + sha256: eb99b295153abce5d683cac8c02e22faab63e50679b937fa1bf67d58bb282878 + url: "https://pub.dev" + source: hosted + version: "4.3.0" + permission_handler_windows: + dependency: transitive + description: + name: permission_handler_windows + sha256: "1a790728016f79a41216d88672dbc5df30e686e811ad4e698bfc51f76ad91f1e" + url: "https://pub.dev" + source: hosted + version: "0.2.1" + 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" + pointer_interceptor: + dependency: transitive + description: + name: pointer_interceptor + sha256: "57210410680379aea8b1b7ed6ae0c3ad349bfd56fe845b8ea934a53344b9d523" + url: "https://pub.dev" + source: hosted + version: "0.10.1+2" + pointer_interceptor_ios: + dependency: transitive + description: + name: pointer_interceptor_ios + sha256: "03c5fa5896080963ab4917eeffda8d28c90f22863a496fb5ba13bc10943e40e4" + url: "https://pub.dev" + source: hosted + version: "0.10.1+1" + pointer_interceptor_platform_interface: + dependency: transitive + description: + name: pointer_interceptor_platform_interface + sha256: "0597b0560e14354baeb23f8375cd612e8bd4841bf8306ecb71fcd0bb78552506" + url: "https://pub.dev" + source: hosted + version: "0.10.0+1" + pointer_interceptor_web: + dependency: transitive + description: + name: pointer_interceptor_web + sha256: "460b600e71de6fcea2b3d5f662c92293c049c4319e27f0829310e5a953b3ee2a" + url: "https://pub.dev" + source: hosted + version: "0.10.3" + pub_semver: + dependency: transitive + description: + name: pub_semver + sha256: "5bfcf68ca79ef689f8990d1160781b4bad40a3bd5e5218ad4076ddb7f4081585" + url: "https://pub.dev" + source: hosted + version: "2.2.0" + quiver: + dependency: transitive + description: + name: quiver + sha256: ea0b925899e64ecdfbf9c7becb60d5b50e706ade44a85b2363be2a22d88117d2 + url: "https://pub.dev" + source: hosted + version: "3.2.2" + sky_engine: + dependency: transitive + description: flutter + source: sdk + version: "0.0.0" + source_span: + dependency: transitive + description: + name: source_span + sha256: "56a02f1f4cd1a2d96303c0144c93bd6d909eea6bee6bf5a0e0b685edbd4c47ab" + url: "https://pub.dev" + source: hosted + version: "1.10.2" + sqflite: + dependency: "direct main" + description: + name: sqflite + sha256: e2297b1da52f127bc7a3da11439985d9b536f75070f3325e62ada69a5c585d03 + url: "https://pub.dev" + source: hosted + version: "2.4.2" + sqflite_android: + dependency: transitive + description: + name: sqflite_android + sha256: "881e28efdcc9950fd8e9bb42713dcf1103e62a2e7168f23c9338d82db13dec40" + url: "https://pub.dev" + source: hosted + version: "2.4.2+3" + sqflite_common: + dependency: transitive + description: + name: sqflite_common + sha256: "6ef422a4525ecc601db6c0a2233ff448c731307906e92cabc9ba292afaae16a6" + url: "https://pub.dev" + source: hosted + version: "2.5.6" + sqflite_darwin: + dependency: transitive + description: + name: sqflite_darwin + sha256: "279832e5cde3fe99e8571879498c9211f3ca6391b0d818df4e17d9fff5c6ccb3" + url: "https://pub.dev" + source: hosted + version: "2.4.2" + sqflite_platform_interface: + dependency: transitive + description: + name: sqflite_platform_interface + sha256: "8dd4515c7bdcae0a785b0062859336de775e8c65db81ae33dd5445f35be61920" + url: "https://pub.dev" + source: hosted + version: "2.4.0" + stack_trace: + dependency: transitive + description: + name: stack_trace + sha256: "8b27215b45d22309b5cddda1aa2b19bdfec9df0e765f2de506401c071d38d1b1" + url: "https://pub.dev" + source: hosted + version: "1.12.1" + stream_channel: + dependency: transitive + description: + name: stream_channel + sha256: "969e04c80b8bcdf826f8f16579c7b14d780458bd97f56d107d3950fdbeef059d" + url: "https://pub.dev" + source: hosted + version: "2.1.4" + string_scanner: + dependency: transitive + description: + name: string_scanner + sha256: "921cd31725b72fe181906c6a94d987c78e3b98c2e205b397ea399d4054872b43" + url: "https://pub.dev" + source: hosted + version: "1.4.1" + synchronized: + dependency: transitive + description: + name: synchronized + sha256: c254ade258ec8282947a0acbbc90b9575b4f19673533ee46f2f6e9b3aeefd7c0 + url: "https://pub.dev" + source: hosted + version: "3.4.0" + term_glyph: + dependency: transitive + description: + name: term_glyph + sha256: "7f554798625ea768a7518313e58f83891c7f5024f88e46e7182a4558850a4b8e" + url: "https://pub.dev" + source: hosted + version: "1.2.2" + test_api: + dependency: transitive + description: + name: test_api + sha256: "8161c84903fd860b26bfdefb7963b3f0b68fee7adea0f59ef805ecca346f0c7a" + url: "https://pub.dev" + source: hosted + version: "0.7.10" + tflite_flutter: + dependency: "direct main" + description: + name: tflite_flutter + sha256: "0bba9040d8decda0960d7abf8eabf32243bf092bc7d0084e8e19681866b0bdbe" + url: "https://pub.dev" + source: hosted + version: "0.12.1" + throttling: + dependency: transitive + description: + name: throttling + sha256: e48a4c681b1838b8bf99c1a4f822efe43bb69132f9a56091cd5b7d931c862255 + url: "https://pub.dev" + source: hosted + version: "2.0.1" + typed_data: + dependency: transitive + description: + name: typed_data + sha256: f9049c039ebfeb4cf7a7104a675823cd72dba8297f264b6637062516699fa006 + url: "https://pub.dev" + source: hosted + version: "1.4.0" + vector_math: + dependency: transitive + description: + name: vector_math + sha256: d530bd74fea330e6e364cda7a85019c434070188383e1cd8d9777ee586914c5b + url: "https://pub.dev" + source: hosted + version: "2.2.0" + virtual_keyboard_multi_language: + dependency: "direct main" + description: + name: virtual_keyboard_multi_language + sha256: dfa79de3a6a885b297146d065ebcd2a576ec837b65ce61d8279b4ee013784035 + url: "https://pub.dev" + source: hosted + version: "1.1.2" + vm_service: + dependency: transitive + description: + name: vm_service + sha256: "45caa6c5917fa127b5dbcfbd1fa60b14e583afdc08bfc96dda38886ca252eb60" + url: "https://pub.dev" + source: hosted + version: "15.0.2" + web: + dependency: transitive + description: + name: web + sha256: "868d88a33d8a87b18ffc05f9f030ba328ffefba92d6c127917a2ba740f9cfe4a" + url: "https://pub.dev" + source: hosted + version: "1.1.1" + xdg_directories: + dependency: transitive + description: + name: xdg_directories + sha256: "7a3f37b05d989967cdddcbb571f1ea834867ae2faa29725fd085180e0883aa15" + url: "https://pub.dev" + source: hosted + version: "1.1.0" + yaml: + dependency: transitive + description: + name: yaml + sha256: b9da305ac7c39faa3f030eccd175340f968459dae4af175130b3fc47e40d76ce + url: "https://pub.dev" + source: hosted + version: "3.1.3" +sdks: + dart: ">=3.11.1 <4.0.0" + flutter: ">=3.38.4" diff --git a/pubspec.yaml b/pubspec.yaml new file mode 100644 index 0000000000000000000000000000000000000000..9332d3a05d8f32a330084e26a2829f1dfe0542df --- /dev/null +++ b/pubspec.yaml @@ -0,0 +1,107 @@ +name: premithus +description: "A new Flutter project." +# The following line prevents the package from being accidentally published to +# pub.dev using `flutter pub publish`. This is preferred for private packages. +publish_to: 'none' # Remove this line if you wish to publish to pub.dev + +# The following defines the version and build number for your application. +# A version number is three numbers separated by dots, like 1.2.43 +# followed by an optional build number separated by a +. +# Both the version and the builder number may be overridden in flutter +# build by specifying --build-name and --build-number, respectively. +# In Android, build-name is used as versionName while build-number used as versionCode. +# Read more about Android versioning at https://developer.android.com/studio/publish/versioning +# In iOS, build-name is used as CFBundleShortVersionString while build-number is used as CFBundleVersion. +# Read more about iOS versioning at +# https://developer.apple.com/library/archive/documentation/General/Reference/InfoPlistKeyReference/Articles/CoreFoundationKeys.html +# In Windows, build-name is used as the major, minor, and patch parts +# of the product and file versions while build-number is used as the build suffix. +version: 1.0.0+1 + +environment: + sdk: ^3.11.1 + +# Dependencies specify other packages that your package needs in order to work. +# To automatically upgrade your package dependencies to the latest versions +# consider running `flutter pub upgrade --major-versions`. Alternatively, +# dependencies can be manually updated by changing the version numbers below to +# the latest version available on pub.dev. To see which dependencies have newer +# versions available, run `flutter pub outdated`. +dependencies: + flutter: + sdk: flutter + + # The following adds the Cupertino Icons font to your application. + # Use with the CupertinoIcons class for iOS style icons. + cupertino_icons: ^1.0.8 + + # Premithius dependencies + flutter_keyboard_visibility: ^6.0.0 + # llama_sdk: + # path: lcpp + tflite_flutter: ^0.12.1 + languagetool_textfield: ^0.1.1 + sqflite: ^2.3.3 + path_provider: ^2.1.2 + permission_handler: ^11.3.0 + flutter_animate: ^4.5.0 + gap: ^3.0.1 + virtual_keyboard_multi_language: any + google_fonts: ^6.2.1 + path: ^1.9.0 + +dev_dependencies: + flutter_test: + sdk: flutter + + # The "flutter_lints" package below contains a set of recommended lints to + # encourage good coding practices. The lint set provided by the package is + # activated in the `analysis_options.yaml` file located at the root of your + # package. See that file for information about deactivating specific lint + # rules and activating additional ones. + flutter_lints: ^6.0.0 + +# For information on the generic Dart part of this file, see the +# following page: https://dart.dev/tools/pub/pubspec + +# The following section is specific to Flutter packages. +flutter: + + # The following line ensures that the Material Icons font is + # included with your application, so that you can use the icons in + # the material Icons class. + uses-material-design: true + + # To add assets to your application, add an assets section, like this: + assets: + - assets/seed_embeddings.json + - assets/blocklist/ + - models/ + # - images/a_dot_burr.jpeg + # - images/a_dot_ham.jpeg + + # An image asset can refer to one or more resolution-specific "variants", see + # https://flutter.dev/to/resolution-aware-images + + # For details regarding adding assets from package dependencies, see + # https://flutter.dev/to/asset-from-package + + # To add custom fonts to your application, add a fonts section here, + # in this "flutter" section. Each entry in this list should have a + # "family" key with the font family name, and a "fonts" key with a + # list giving the asset and other descriptors for the font. For + # example: + # fonts: + # - family: Schyler + # fonts: + # - asset: fonts/Schyler-Regular.ttf + # - asset: fonts/Schyler-Italic.ttf + # style: italic + # - family: Trajan Pro + # fonts: + # - asset: fonts/TrajanPro.ttf + # - asset: fonts/TrajanPro_Bold.ttf + # weight: 700 + # + # For details regarding fonts from package dependencies, + # see https://flutter.dev/to/font-from-package diff --git a/style.css b/style.css new file mode 100644 index 0000000000000000000000000000000000000000..114adf441e9032febb46bc056b2a8bb651075f0d --- /dev/null +++ b/style.css @@ -0,0 +1,28 @@ +body { + padding: 2rem; + font-family: -apple-system, BlinkMacSystemFont, "Arial", sans-serif; +} + +h1 { + font-size: 16px; + margin-top: 0; +} + +p { + color: rgb(107, 114, 128); + font-size: 15px; + margin-bottom: 10px; + margin-top: 5px; +} + +.card { + max-width: 620px; + margin: 0 auto; + padding: 16px; + border: 1px solid lightgray; + border-radius: 16px; +} + +.card p:last-child { + margin-bottom: 0; +} diff --git a/train_rf.py b/train_rf.py new file mode 100644 index 0000000000000000000000000000000000000000..c22e9375b671f73f0fb4e512d77b2eeda393b1cd --- /dev/null +++ b/train_rf.py @@ -0,0 +1,149 @@ +import pandas as pd +import numpy as np +from datasets import load_dataset +from sklearn.ensemble import RandomForestClassifier +from sklearn.model_selection import train_test_split +from sklearn.metrics import classification_report +import m2cgen as m2c +import re + +print("Loading dataset alanjoshua2005/india-spam-sms...") +dataset = load_dataset("alanjoshua2005/india-spam-sms") + +# Usually dataset has 'train' split which is a list of dicts. Let's make a dataframe +df = pd.DataFrame(dataset['train']) +# Let's see columns +print(df.columns) +# Typically it has 'v1' mapping to label and 'v2' mapping to text, or 'label' and 'text', or 'Message' and 'Category' +if 'Message' in df.columns and 'Category' in df.columns: + df['text'] = df['Message'] + df['label'] = df['Category'].apply(lambda x: 1 if x == 'spam' else 0) +elif 'text' in df.columns and 'label' in df.columns: + pass +elif 'v1' in df.columns and 'v2' in df.columns: + df['text'] = df['v2'] + df['label'] = df['v1'].apply(lambda x: 1 if x == 'spam' else 0) +else: + # try generically + for col in df.columns: + if 'text' in col.lower() or 'msg' in col.lower() or 'message' in col.lower(): + df['text'] = df[col] + if 'label' in col.lower() or 'spam' in col.lower() or 'category' in col.lower(): + df['label'] = df[col] + if df['label'].dtype == object: + df['label'] = df['label'].apply(lambda x: 1 if 'spam' in str(x).lower() else 0) + +print(df.head()) + +def extract_features(row): + text = str(row['text']).lower() + + # 1. senderAgeScore (mock context) + # 2. senderInContacts + # 3. senderMessageCount + # 4. senderCarrierScore + # We will simulate these based on label, because text doesn't have it. + is_spam = row['label'] == 1 + + senderAgeScore = np.random.uniform(0.0, 0.3) if is_spam else np.random.uniform(0.5, 1.0) + senderInContacts = 0.0 if is_spam else float(np.random.rand() > 0.2) + senderMessageCount = np.random.randint(0, 3) if is_spam else np.random.randint(10, 100) + senderCarrierScore = np.random.uniform(0.0, 0.4) if is_spam else np.random.uniform(0.6, 1.0) + + # 5. urgencyScore (0.0 to 1.0) + urgent_words = ['urgent', 'hurry', 'limited', 'immediate', 'action required', 'alert', 'warning', 'expires', 'claim'] + urgencyScore = sum([1 for w in urgent_words if w in text]) / len(urgent_words) + + # 6. domainCount + domain_matches = re.findall(r"(http[s]?://|www\.)[^\s]+", text) + domainCount = len(domain_matches) + + # 7. domainLevenshtein (simulated, no actual domain extraction here) + domainLevenshtein = np.random.uniform(0.2, 0.9) if (is_spam and domainCount > 0) else 1.0 + + # 8. containsMoneyAction + money_words = ['rs', '₹', 'free', 'win', 'prize', 'cash', 'money', 'credit', 'loan', 'offer', 'pay', 'collect', 'bank'] + containsMoneyAction = float(any(w in text for w in money_words)) + + # 9. capsRatio + orig_text = str(row['text']) + caps_count = sum(1 for c in orig_text if c.isupper()) + letters_count = sum(1 for c in orig_text if c.isalpha()) + capsRatio = caps_count / letters_count if letters_count > 0 else 0.0 + + # 10. hourOfDay (spam often sent at odd hours) + hourOfDay = float(np.random.choice([0,1,2,3,4,22,23])) if is_spam else float(np.random.randint(8, 20)) + + # 11. isWeekend + isWeekend = float(np.random.rand() > (0.3 if is_spam else 0.8)) + + # 12. isFestivalPeriod + isFestivalPeriod = float(np.random.rand() > 0.8) + + # 13. recentScamSenderSim + recentScamSenderSim = np.random.uniform(0.5, 1.0) if is_spam else np.random.uniform(0.0, 0.2) + + return [ + senderAgeScore, senderInContacts, float(senderMessageCount), senderCarrierScore, + urgencyScore, float(domainCount), domainLevenshtein, containsMoneyAction, capsRatio, + hourOfDay, isWeekend, isFestivalPeriod, recentScamSenderSim + ] + +print("Extracting features...") +X = np.array([extract_features(row) for _, row in df.iterrows()]) +y = df['label'].values + +X_train, X_test, y_train, y_test = train_test_split(X, y, test_size=0.2, random_state=42) + +print("Training Random Forest...") +clf = RandomForestClassifier(n_estimators=15, max_depth=5, random_state=42) +clf.fit(X_train, y_train) + +print("Evaluating...") +preds = clf.predict(X_test) +print(classification_report(y_test, preds)) + +print("Exporting model to Dart with m2cgen...") +dart_code = m2c.export_to_dart(clf) + +# Write to our model file +file_path = "lib/kavacha/models/random_forest_model.dart" +header = """// Auto-generated using m2cgen +import 'sms_feature_vector.dart'; + +class RandomForestModel { + double score(SmsFeatureVector features) { + List input = [ + features.senderAgeScore, + features.senderInContacts ? 1.0 : 0.0, + features.senderMessageCount.toDouble(), + features.senderCarrierScore, + features.urgencyScore, + features.domainCount.toDouble(), + features.domainLevenshtein, + features.containsMoneyAction ? 1.0 : 0.0, + features.capsRatio, + features.hourOfDay.toDouble(), + features.isWeekend ? 1.0 : 0.0, + features.isFestivalPeriod ? 1.0 : 0.0, + features.recentScamSenderSim + ]; + List output = score_features(input); + // output[1] is the probability of class 1 (spam) + return output[1]; + } + +""" + +with open(file_path, "w") as f: + f.write(header) + # The generated code usually has a class or double[] score(double[] input) + # We will just write it straight out, maybe replace the class wrapper + code = dart_code.replace("double[]", "List").replace("public double[] score", "List score_features") + # m2cgen generates a single function / class. We strip "public class Model {" etc if present. + # Luckily Dart export is typically `List score(List input)` + f.write(code) + f.write("\n}\n") + +print("Done writing to " + file_path) + diff --git a/web/index.html b/web/index.html new file mode 100644 index 0000000000000000000000000000000000000000..0c1e9e448fb6d0aa8bbf7bd90a8004d1e8a55277 --- /dev/null +++ b/web/index.html @@ -0,0 +1,46 @@ + + + + + + + + + + + + + + + + + + + + premithus + + + + + + + diff --git a/web/manifest.json b/web/manifest.json new file mode 100644 index 0000000000000000000000000000000000000000..d77b182c0a868a744e7c563427c43575478bb211 --- /dev/null +++ b/web/manifest.json @@ -0,0 +1,35 @@ +{ + "name": "premithus", + "short_name": "premithus", + "start_url": ".", + "display": "standalone", + "background_color": "#0175C2", + "theme_color": "#0175C2", + "description": "A new Flutter project.", + "orientation": "portrait-primary", + "prefer_related_applications": false, + "icons": [ + { + "src": "icons/Icon-192.png", + "sizes": "192x192", + "type": "image/png" + }, + { + "src": "icons/Icon-512.png", + "sizes": "512x512", + "type": "image/png" + }, + { + "src": "icons/Icon-maskable-192.png", + "sizes": "192x192", + "type": "image/png", + "purpose": "maskable" + }, + { + "src": "icons/Icon-maskable-512.png", + "sizes": "512x512", + "type": "image/png", + "purpose": "maskable" + } + ] +} diff --git a/windows/.gitignore b/windows/.gitignore new file mode 100644 index 0000000000000000000000000000000000000000..d492d0d98c8fdc9f93ad2543bb4f531803e9df72 --- /dev/null +++ b/windows/.gitignore @@ -0,0 +1,17 @@ +flutter/ephemeral/ + +# Visual Studio user-specific files. +*.suo +*.user +*.userosscache +*.sln.docstates + +# Visual Studio build-related files. +x64/ +x86/ + +# Visual Studio cache files +# files ending in .cache can be ignored +*.[Cc]ache +# but keep track of directories ending in .cache +!*.[Cc]ache/ diff --git a/windows/CMakeLists.txt b/windows/CMakeLists.txt new file mode 100644 index 0000000000000000000000000000000000000000..4a26779f45c836c3f984807cf67f802d7022ea6d --- /dev/null +++ b/windows/CMakeLists.txt @@ -0,0 +1,108 @@ +# Project-level configuration. +cmake_minimum_required(VERSION 3.14) +project(premithus LANGUAGES CXX) + +# The name of the executable created for the application. Change this to change +# the on-disk name of your application. +set(BINARY_NAME "premithus") + +# Explicitly opt in to modern CMake behaviors to avoid warnings with recent +# versions of CMake. +cmake_policy(VERSION 3.14...3.25) + +# Define build configuration option. +get_property(IS_MULTICONFIG GLOBAL PROPERTY GENERATOR_IS_MULTI_CONFIG) +if(IS_MULTICONFIG) + set(CMAKE_CONFIGURATION_TYPES "Debug;Profile;Release" + CACHE STRING "" FORCE) +else() + if(NOT CMAKE_BUILD_TYPE AND NOT CMAKE_CONFIGURATION_TYPES) + set(CMAKE_BUILD_TYPE "Debug" CACHE + STRING "Flutter build mode" FORCE) + set_property(CACHE CMAKE_BUILD_TYPE PROPERTY STRINGS + "Debug" "Profile" "Release") + endif() +endif() +# Define settings for the Profile build mode. +set(CMAKE_EXE_LINKER_FLAGS_PROFILE "${CMAKE_EXE_LINKER_FLAGS_RELEASE}") +set(CMAKE_SHARED_LINKER_FLAGS_PROFILE "${CMAKE_SHARED_LINKER_FLAGS_RELEASE}") +set(CMAKE_C_FLAGS_PROFILE "${CMAKE_C_FLAGS_RELEASE}") +set(CMAKE_CXX_FLAGS_PROFILE "${CMAKE_CXX_FLAGS_RELEASE}") + +# Use Unicode for all projects. +add_definitions(-DUNICODE -D_UNICODE) + +# Compilation settings that should be applied to most targets. +# +# Be cautious about adding new options here, as plugins use this function by +# default. In most cases, you should add new options to specific targets instead +# of modifying this function. +function(APPLY_STANDARD_SETTINGS TARGET) + target_compile_features(${TARGET} PUBLIC cxx_std_17) + target_compile_options(${TARGET} PRIVATE /W4 /WX /wd"4100") + target_compile_options(${TARGET} PRIVATE /EHsc) + target_compile_definitions(${TARGET} PRIVATE "_HAS_EXCEPTIONS=0") + target_compile_definitions(${TARGET} PRIVATE "$<$:_DEBUG>") +endfunction() + +# Flutter library and tool build rules. +set(FLUTTER_MANAGED_DIR "${CMAKE_CURRENT_SOURCE_DIR}/flutter") +add_subdirectory(${FLUTTER_MANAGED_DIR}) + +# Application build; see runner/CMakeLists.txt. +add_subdirectory("runner") + + +# Generated plugin build rules, which manage building the plugins and adding +# them to the application. +include(flutter/generated_plugins.cmake) + + +# === Installation === +# Support files are copied into place next to the executable, so that it can +# run in place. This is done instead of making a separate bundle (as on Linux) +# so that building and running from within Visual Studio will work. +set(BUILD_BUNDLE_DIR "$") +# Make the "install" step default, as it's required to run. +set(CMAKE_VS_INCLUDE_INSTALL_TO_DEFAULT_BUILD 1) +if(CMAKE_INSTALL_PREFIX_INITIALIZED_TO_DEFAULT) + set(CMAKE_INSTALL_PREFIX "${BUILD_BUNDLE_DIR}" CACHE PATH "..." FORCE) +endif() + +set(INSTALL_BUNDLE_DATA_DIR "${CMAKE_INSTALL_PREFIX}/data") +set(INSTALL_BUNDLE_LIB_DIR "${CMAKE_INSTALL_PREFIX}") + +install(TARGETS ${BINARY_NAME} RUNTIME DESTINATION "${CMAKE_INSTALL_PREFIX}" + COMPONENT Runtime) + +install(FILES "${FLUTTER_ICU_DATA_FILE}" DESTINATION "${INSTALL_BUNDLE_DATA_DIR}" + COMPONENT Runtime) + +install(FILES "${FLUTTER_LIBRARY}" DESTINATION "${INSTALL_BUNDLE_LIB_DIR}" + COMPONENT Runtime) + +if(PLUGIN_BUNDLED_LIBRARIES) + install(FILES "${PLUGIN_BUNDLED_LIBRARIES}" + DESTINATION "${INSTALL_BUNDLE_LIB_DIR}" + COMPONENT Runtime) +endif() + +# Copy the native assets provided by the build.dart from all packages. +set(NATIVE_ASSETS_DIR "${PROJECT_BUILD_DIR}native_assets/windows/") +install(DIRECTORY "${NATIVE_ASSETS_DIR}" + DESTINATION "${INSTALL_BUNDLE_LIB_DIR}" + COMPONENT Runtime) + +# Fully re-copy the assets directory on each build to avoid having stale files +# from a previous install. +set(FLUTTER_ASSET_DIR_NAME "flutter_assets") +install(CODE " + file(REMOVE_RECURSE \"${INSTALL_BUNDLE_DATA_DIR}/${FLUTTER_ASSET_DIR_NAME}\") + " COMPONENT Runtime) +install(DIRECTORY "${PROJECT_BUILD_DIR}/${FLUTTER_ASSET_DIR_NAME}" + DESTINATION "${INSTALL_BUNDLE_DATA_DIR}" COMPONENT Runtime) + +# Install the AOT library on non-Debug builds only. +install(FILES "${AOT_LIBRARY}" DESTINATION "${INSTALL_BUNDLE_DATA_DIR}" + CONFIGURATIONS Profile;Release + COMPONENT Runtime) diff --git a/windows/flutter/CMakeLists.txt b/windows/flutter/CMakeLists.txt new file mode 100644 index 0000000000000000000000000000000000000000..903f4899d6fced0eb941e159f7322b21b320c40c --- /dev/null +++ b/windows/flutter/CMakeLists.txt @@ -0,0 +1,109 @@ +# This file controls Flutter-level build steps. It should not be edited. +cmake_minimum_required(VERSION 3.14) + +set(EPHEMERAL_DIR "${CMAKE_CURRENT_SOURCE_DIR}/ephemeral") + +# Configuration provided via flutter tool. +include(${EPHEMERAL_DIR}/generated_config.cmake) + +# TODO: Move the rest of this into files in ephemeral. See +# https://github.com/flutter/flutter/issues/57146. +set(WRAPPER_ROOT "${EPHEMERAL_DIR}/cpp_client_wrapper") + +# Set fallback configurations for older versions of the flutter tool. +if (NOT DEFINED FLUTTER_TARGET_PLATFORM) + set(FLUTTER_TARGET_PLATFORM "windows-x64") +endif() + +# === Flutter Library === +set(FLUTTER_LIBRARY "${EPHEMERAL_DIR}/flutter_windows.dll") + +# Published to parent scope for install step. +set(FLUTTER_LIBRARY ${FLUTTER_LIBRARY} PARENT_SCOPE) +set(FLUTTER_ICU_DATA_FILE "${EPHEMERAL_DIR}/icudtl.dat" PARENT_SCOPE) +set(PROJECT_BUILD_DIR "${PROJECT_DIR}/build/" PARENT_SCOPE) +set(AOT_LIBRARY "${PROJECT_DIR}/build/windows/app.so" PARENT_SCOPE) + +list(APPEND FLUTTER_LIBRARY_HEADERS + "flutter_export.h" + "flutter_windows.h" + "flutter_messenger.h" + "flutter_plugin_registrar.h" + "flutter_texture_registrar.h" +) +list(TRANSFORM FLUTTER_LIBRARY_HEADERS PREPEND "${EPHEMERAL_DIR}/") +add_library(flutter INTERFACE) +target_include_directories(flutter INTERFACE + "${EPHEMERAL_DIR}" +) +target_link_libraries(flutter INTERFACE "${FLUTTER_LIBRARY}.lib") +add_dependencies(flutter flutter_assemble) + +# === Wrapper === +list(APPEND CPP_WRAPPER_SOURCES_CORE + "core_implementations.cc" + "standard_codec.cc" +) +list(TRANSFORM CPP_WRAPPER_SOURCES_CORE PREPEND "${WRAPPER_ROOT}/") +list(APPEND CPP_WRAPPER_SOURCES_PLUGIN + "plugin_registrar.cc" +) +list(TRANSFORM CPP_WRAPPER_SOURCES_PLUGIN PREPEND "${WRAPPER_ROOT}/") +list(APPEND CPP_WRAPPER_SOURCES_APP + "flutter_engine.cc" + "flutter_view_controller.cc" +) +list(TRANSFORM CPP_WRAPPER_SOURCES_APP PREPEND "${WRAPPER_ROOT}/") + +# Wrapper sources needed for a plugin. +add_library(flutter_wrapper_plugin STATIC + ${CPP_WRAPPER_SOURCES_CORE} + ${CPP_WRAPPER_SOURCES_PLUGIN} +) +apply_standard_settings(flutter_wrapper_plugin) +set_target_properties(flutter_wrapper_plugin PROPERTIES + POSITION_INDEPENDENT_CODE ON) +set_target_properties(flutter_wrapper_plugin PROPERTIES + CXX_VISIBILITY_PRESET hidden) +target_link_libraries(flutter_wrapper_plugin PUBLIC flutter) +target_include_directories(flutter_wrapper_plugin PUBLIC + "${WRAPPER_ROOT}/include" +) +add_dependencies(flutter_wrapper_plugin flutter_assemble) + +# Wrapper sources needed for the runner. +add_library(flutter_wrapper_app STATIC + ${CPP_WRAPPER_SOURCES_CORE} + ${CPP_WRAPPER_SOURCES_APP} +) +apply_standard_settings(flutter_wrapper_app) +target_link_libraries(flutter_wrapper_app PUBLIC flutter) +target_include_directories(flutter_wrapper_app PUBLIC + "${WRAPPER_ROOT}/include" +) +add_dependencies(flutter_wrapper_app flutter_assemble) + +# === Flutter tool backend === +# _phony_ is a non-existent file to force this command to run every time, +# since currently there's no way to get a full input/output list from the +# flutter tool. +set(PHONY_OUTPUT "${CMAKE_CURRENT_BINARY_DIR}/_phony_") +set_source_files_properties("${PHONY_OUTPUT}" PROPERTIES SYMBOLIC TRUE) +add_custom_command( + OUTPUT ${FLUTTER_LIBRARY} ${FLUTTER_LIBRARY_HEADERS} + ${CPP_WRAPPER_SOURCES_CORE} ${CPP_WRAPPER_SOURCES_PLUGIN} + ${CPP_WRAPPER_SOURCES_APP} + ${PHONY_OUTPUT} + COMMAND ${CMAKE_COMMAND} -E env + ${FLUTTER_TOOL_ENVIRONMENT} + "${FLUTTER_ROOT}/packages/flutter_tools/bin/tool_backend.bat" + ${FLUTTER_TARGET_PLATFORM} $ + VERBATIM +) +add_custom_target(flutter_assemble DEPENDS + "${FLUTTER_LIBRARY}" + ${FLUTTER_LIBRARY_HEADERS} + ${CPP_WRAPPER_SOURCES_CORE} + ${CPP_WRAPPER_SOURCES_PLUGIN} + ${CPP_WRAPPER_SOURCES_APP} +) diff --git a/windows/flutter/generated_plugin_registrant.cc b/windows/flutter/generated_plugin_registrant.cc new file mode 100644 index 0000000000000000000000000000000000000000..48de52bffad9b08b90558e5c760d9f7694d030d2 --- /dev/null +++ b/windows/flutter/generated_plugin_registrant.cc @@ -0,0 +1,14 @@ +// +// Generated file. Do not edit. +// + +// clang-format off + +#include "generated_plugin_registrant.h" + +#include + +void RegisterPlugins(flutter::PluginRegistry* registry) { + PermissionHandlerWindowsPluginRegisterWithRegistrar( + registry->GetRegistrarForPlugin("PermissionHandlerWindowsPlugin")); +} diff --git a/windows/flutter/generated_plugin_registrant.h b/windows/flutter/generated_plugin_registrant.h new file mode 100644 index 0000000000000000000000000000000000000000..dc139d85a93101cc0f6e9db03a3e1a9f68e8dd7e --- /dev/null +++ b/windows/flutter/generated_plugin_registrant.h @@ -0,0 +1,15 @@ +// +// Generated file. Do not edit. +// + +// clang-format off + +#ifndef GENERATED_PLUGIN_REGISTRANT_ +#define GENERATED_PLUGIN_REGISTRANT_ + +#include + +// Registers Flutter plugins. +void RegisterPlugins(flutter::PluginRegistry* registry); + +#endif // GENERATED_PLUGIN_REGISTRANT_ diff --git a/windows/flutter/generated_plugins.cmake b/windows/flutter/generated_plugins.cmake new file mode 100644 index 0000000000000000000000000000000000000000..cacfdd8f63c67d1f08e17dacb7ceadf18376d294 --- /dev/null +++ b/windows/flutter/generated_plugins.cmake @@ -0,0 +1,25 @@ +# +# Generated file, do not edit. +# + +list(APPEND FLUTTER_PLUGIN_LIST + permission_handler_windows +) + +list(APPEND FLUTTER_FFI_PLUGIN_LIST + tflite_flutter +) + +set(PLUGIN_BUNDLED_LIBRARIES) + +foreach(plugin ${FLUTTER_PLUGIN_LIST}) + add_subdirectory(flutter/ephemeral/.plugin_symlinks/${plugin}/windows plugins/${plugin}) + target_link_libraries(${BINARY_NAME} PRIVATE ${plugin}_plugin) + list(APPEND PLUGIN_BUNDLED_LIBRARIES $) + list(APPEND PLUGIN_BUNDLED_LIBRARIES ${${plugin}_bundled_libraries}) +endforeach(plugin) + +foreach(ffi_plugin ${FLUTTER_FFI_PLUGIN_LIST}) + add_subdirectory(flutter/ephemeral/.plugin_symlinks/${ffi_plugin}/windows plugins/${ffi_plugin}) + list(APPEND PLUGIN_BUNDLED_LIBRARIES ${${ffi_plugin}_bundled_libraries}) +endforeach(ffi_plugin) diff --git a/windows/runner/CMakeLists.txt b/windows/runner/CMakeLists.txt new file mode 100644 index 0000000000000000000000000000000000000000..394917c053a04daa76d8b94f0a02db0bd99e1034 --- /dev/null +++ b/windows/runner/CMakeLists.txt @@ -0,0 +1,40 @@ +cmake_minimum_required(VERSION 3.14) +project(runner LANGUAGES CXX) + +# Define the application target. To change its name, change BINARY_NAME in the +# top-level CMakeLists.txt, not the value here, or `flutter run` will no longer +# work. +# +# Any new source files that you add to the application should be added here. +add_executable(${BINARY_NAME} WIN32 + "flutter_window.cpp" + "main.cpp" + "utils.cpp" + "win32_window.cpp" + "${FLUTTER_MANAGED_DIR}/generated_plugin_registrant.cc" + "Runner.rc" + "runner.exe.manifest" +) + +# Apply the standard set of build settings. This can be removed for applications +# that need different build settings. +apply_standard_settings(${BINARY_NAME}) + +# Add preprocessor definitions for the build version. +target_compile_definitions(${BINARY_NAME} PRIVATE "FLUTTER_VERSION=\"${FLUTTER_VERSION}\"") +target_compile_definitions(${BINARY_NAME} PRIVATE "FLUTTER_VERSION_MAJOR=${FLUTTER_VERSION_MAJOR}") +target_compile_definitions(${BINARY_NAME} PRIVATE "FLUTTER_VERSION_MINOR=${FLUTTER_VERSION_MINOR}") +target_compile_definitions(${BINARY_NAME} PRIVATE "FLUTTER_VERSION_PATCH=${FLUTTER_VERSION_PATCH}") +target_compile_definitions(${BINARY_NAME} PRIVATE "FLUTTER_VERSION_BUILD=${FLUTTER_VERSION_BUILD}") + +# Disable Windows macros that collide with C++ standard library functions. +target_compile_definitions(${BINARY_NAME} PRIVATE "NOMINMAX") + +# Add dependency libraries and include directories. Add any application-specific +# dependencies here. +target_link_libraries(${BINARY_NAME} PRIVATE flutter flutter_wrapper_app) +target_link_libraries(${BINARY_NAME} PRIVATE "dwmapi.lib") +target_include_directories(${BINARY_NAME} PRIVATE "${CMAKE_SOURCE_DIR}") + +# Run the Flutter tool portions of the build. This must not be removed. +add_dependencies(${BINARY_NAME} flutter_assemble) diff --git a/windows/runner/Runner.rc b/windows/runner/Runner.rc new file mode 100644 index 0000000000000000000000000000000000000000..835614f07a213a979b9c1a2e2e82080feb9f2915 --- /dev/null +++ b/windows/runner/Runner.rc @@ -0,0 +1,121 @@ +// Microsoft Visual C++ generated resource script. +// +#pragma code_page(65001) +#include "resource.h" + +#define APSTUDIO_READONLY_SYMBOLS +///////////////////////////////////////////////////////////////////////////// +// +// Generated from the TEXTINCLUDE 2 resource. +// +#include "winres.h" + +///////////////////////////////////////////////////////////////////////////// +#undef APSTUDIO_READONLY_SYMBOLS + +///////////////////////////////////////////////////////////////////////////// +// English (United States) resources + +#if !defined(AFX_RESOURCE_DLL) || defined(AFX_TARG_ENU) +LANGUAGE LANG_ENGLISH, SUBLANG_ENGLISH_US + +#ifdef APSTUDIO_INVOKED +///////////////////////////////////////////////////////////////////////////// +// +// TEXTINCLUDE +// + +1 TEXTINCLUDE +BEGIN + "resource.h\0" +END + +2 TEXTINCLUDE +BEGIN + "#include ""winres.h""\r\n" + "\0" +END + +3 TEXTINCLUDE +BEGIN + "\r\n" + "\0" +END + +#endif // APSTUDIO_INVOKED + + +///////////////////////////////////////////////////////////////////////////// +// +// Icon +// + +// Icon with lowest ID value placed first to ensure application icon +// remains consistent on all systems. +IDI_APP_ICON ICON "resources\\app_icon.ico" + + +///////////////////////////////////////////////////////////////////////////// +// +// Version +// + +#if defined(FLUTTER_VERSION_MAJOR) && defined(FLUTTER_VERSION_MINOR) && defined(FLUTTER_VERSION_PATCH) && defined(FLUTTER_VERSION_BUILD) +#define VERSION_AS_NUMBER FLUTTER_VERSION_MAJOR,FLUTTER_VERSION_MINOR,FLUTTER_VERSION_PATCH,FLUTTER_VERSION_BUILD +#else +#define VERSION_AS_NUMBER 1,0,0,0 +#endif + +#if defined(FLUTTER_VERSION) +#define VERSION_AS_STRING FLUTTER_VERSION +#else +#define VERSION_AS_STRING "1.0.0" +#endif + +VS_VERSION_INFO VERSIONINFO + FILEVERSION VERSION_AS_NUMBER + PRODUCTVERSION VERSION_AS_NUMBER + FILEFLAGSMASK VS_FFI_FILEFLAGSMASK +#ifdef _DEBUG + FILEFLAGS VS_FF_DEBUG +#else + FILEFLAGS 0x0L +#endif + FILEOS VOS__WINDOWS32 + FILETYPE VFT_APP + FILESUBTYPE 0x0L +BEGIN + BLOCK "StringFileInfo" + BEGIN + BLOCK "040904e4" + BEGIN + VALUE "CompanyName", "in.inmodel" "\0" + VALUE "FileDescription", "premithus" "\0" + VALUE "FileVersion", VERSION_AS_STRING "\0" + VALUE "InternalName", "premithus" "\0" + VALUE "LegalCopyright", "Copyright (C) 2026 in.inmodel. All rights reserved." "\0" + VALUE "OriginalFilename", "premithus.exe" "\0" + VALUE "ProductName", "premithus" "\0" + VALUE "ProductVersion", VERSION_AS_STRING "\0" + END + END + BLOCK "VarFileInfo" + BEGIN + VALUE "Translation", 0x409, 1252 + END +END + +#endif // English (United States) resources +///////////////////////////////////////////////////////////////////////////// + + + +#ifndef APSTUDIO_INVOKED +///////////////////////////////////////////////////////////////////////////// +// +// Generated from the TEXTINCLUDE 3 resource. +// + + +///////////////////////////////////////////////////////////////////////////// +#endif // not APSTUDIO_INVOKED diff --git a/windows/runner/flutter_window.cpp b/windows/runner/flutter_window.cpp new file mode 100644 index 0000000000000000000000000000000000000000..955ee3038f988929fac2dedb6a307ebd45dfcfd7 --- /dev/null +++ b/windows/runner/flutter_window.cpp @@ -0,0 +1,71 @@ +#include "flutter_window.h" + +#include + +#include "flutter/generated_plugin_registrant.h" + +FlutterWindow::FlutterWindow(const flutter::DartProject& project) + : project_(project) {} + +FlutterWindow::~FlutterWindow() {} + +bool FlutterWindow::OnCreate() { + if (!Win32Window::OnCreate()) { + return false; + } + + RECT frame = GetClientArea(); + + // The size here must match the window dimensions to avoid unnecessary surface + // creation / destruction in the startup path. + flutter_controller_ = std::make_unique( + frame.right - frame.left, frame.bottom - frame.top, project_); + // Ensure that basic setup of the controller was successful. + if (!flutter_controller_->engine() || !flutter_controller_->view()) { + return false; + } + RegisterPlugins(flutter_controller_->engine()); + SetChildContent(flutter_controller_->view()->GetNativeWindow()); + + flutter_controller_->engine()->SetNextFrameCallback([&]() { + this->Show(); + }); + + // Flutter can complete the first frame before the "show window" callback is + // registered. The following call ensures a frame is pending to ensure the + // window is shown. It is a no-op if the first frame hasn't completed yet. + flutter_controller_->ForceRedraw(); + + return true; +} + +void FlutterWindow::OnDestroy() { + if (flutter_controller_) { + flutter_controller_ = nullptr; + } + + Win32Window::OnDestroy(); +} + +LRESULT +FlutterWindow::MessageHandler(HWND hwnd, UINT const message, + WPARAM const wparam, + LPARAM const lparam) noexcept { + // Give Flutter, including plugins, an opportunity to handle window messages. + if (flutter_controller_) { + std::optional result = + flutter_controller_->HandleTopLevelWindowProc(hwnd, message, wparam, + lparam); + if (result) { + return *result; + } + } + + switch (message) { + case WM_FONTCHANGE: + flutter_controller_->engine()->ReloadSystemFonts(); + break; + } + + return Win32Window::MessageHandler(hwnd, message, wparam, lparam); +} diff --git a/windows/runner/flutter_window.h b/windows/runner/flutter_window.h new file mode 100644 index 0000000000000000000000000000000000000000..6da0652f05f28fc6950cec20ebdfbae89b665479 --- /dev/null +++ b/windows/runner/flutter_window.h @@ -0,0 +1,33 @@ +#ifndef RUNNER_FLUTTER_WINDOW_H_ +#define RUNNER_FLUTTER_WINDOW_H_ + +#include +#include + +#include + +#include "win32_window.h" + +// A window that does nothing but host a Flutter view. +class FlutterWindow : public Win32Window { + public: + // Creates a new FlutterWindow hosting a Flutter view running |project|. + explicit FlutterWindow(const flutter::DartProject& project); + virtual ~FlutterWindow(); + + protected: + // Win32Window: + bool OnCreate() override; + void OnDestroy() override; + LRESULT MessageHandler(HWND window, UINT const message, WPARAM const wparam, + LPARAM const lparam) noexcept override; + + private: + // The project to run. + flutter::DartProject project_; + + // The Flutter instance hosted by this window. + std::unique_ptr flutter_controller_; +}; + +#endif // RUNNER_FLUTTER_WINDOW_H_ diff --git a/windows/runner/main.cpp b/windows/runner/main.cpp new file mode 100644 index 0000000000000000000000000000000000000000..205b8472a0b82843010d8e80f82f20f7c4610613 --- /dev/null +++ b/windows/runner/main.cpp @@ -0,0 +1,43 @@ +#include +#include +#include + +#include "flutter_window.h" +#include "utils.h" + +int APIENTRY wWinMain(_In_ HINSTANCE instance, _In_opt_ HINSTANCE prev, + _In_ wchar_t *command_line, _In_ int show_command) { + // Attach to console when present (e.g., 'flutter run') or create a + // new console when running with a debugger. + if (!::AttachConsole(ATTACH_PARENT_PROCESS) && ::IsDebuggerPresent()) { + CreateAndAttachConsole(); + } + + // Initialize COM, so that it is available for use in the library and/or + // plugins. + ::CoInitializeEx(nullptr, COINIT_APARTMENTTHREADED); + + flutter::DartProject project(L"data"); + + std::vector command_line_arguments = + GetCommandLineArguments(); + + project.set_dart_entrypoint_arguments(std::move(command_line_arguments)); + + FlutterWindow window(project); + Win32Window::Point origin(10, 10); + Win32Window::Size size(1280, 720); + if (!window.Create(L"premithus", origin, size)) { + return EXIT_FAILURE; + } + window.SetQuitOnClose(true); + + ::MSG msg; + while (::GetMessage(&msg, nullptr, 0, 0)) { + ::TranslateMessage(&msg); + ::DispatchMessage(&msg); + } + + ::CoUninitialize(); + return EXIT_SUCCESS; +} diff --git a/windows/runner/resource.h b/windows/runner/resource.h new file mode 100644 index 0000000000000000000000000000000000000000..66a65d1e4a79f230031ec0e0959a721039e7282f --- /dev/null +++ b/windows/runner/resource.h @@ -0,0 +1,16 @@ +//{{NO_DEPENDENCIES}} +// Microsoft Visual C++ generated include file. +// Used by Runner.rc +// +#define IDI_APP_ICON 101 + +// Next default values for new objects +// +#ifdef APSTUDIO_INVOKED +#ifndef APSTUDIO_READONLY_SYMBOLS +#define _APS_NEXT_RESOURCE_VALUE 102 +#define _APS_NEXT_COMMAND_VALUE 40001 +#define _APS_NEXT_CONTROL_VALUE 1001 +#define _APS_NEXT_SYMED_VALUE 101 +#endif +#endif diff --git a/windows/runner/resources/app_icon.ico b/windows/runner/resources/app_icon.ico new file mode 100644 index 0000000000000000000000000000000000000000..c04e20caf6370ebb9253ad831cc31de4a9c965f6 Binary files /dev/null and b/windows/runner/resources/app_icon.ico differ diff --git a/windows/runner/runner.exe.manifest b/windows/runner/runner.exe.manifest new file mode 100644 index 0000000000000000000000000000000000000000..153653e8d67f81b901d28257a65908f3278e058d --- /dev/null +++ b/windows/runner/runner.exe.manifest @@ -0,0 +1,14 @@ + + + + + PerMonitorV2 + + + + + + + + + diff --git a/windows/runner/utils.cpp b/windows/runner/utils.cpp new file mode 100644 index 0000000000000000000000000000000000000000..3a0b46511a71b464dac72d693faae6ea0f7e3b2e --- /dev/null +++ b/windows/runner/utils.cpp @@ -0,0 +1,65 @@ +#include "utils.h" + +#include +#include +#include +#include + +#include + +void CreateAndAttachConsole() { + if (::AllocConsole()) { + FILE *unused; + if (freopen_s(&unused, "CONOUT$", "w", stdout)) { + _dup2(_fileno(stdout), 1); + } + if (freopen_s(&unused, "CONOUT$", "w", stderr)) { + _dup2(_fileno(stdout), 2); + } + std::ios::sync_with_stdio(); + FlutterDesktopResyncOutputStreams(); + } +} + +std::vector GetCommandLineArguments() { + // Convert the UTF-16 command line arguments to UTF-8 for the Engine to use. + int argc; + wchar_t** argv = ::CommandLineToArgvW(::GetCommandLineW(), &argc); + if (argv == nullptr) { + return std::vector(); + } + + std::vector command_line_arguments; + + // Skip the first argument as it's the binary name. + for (int i = 1; i < argc; i++) { + command_line_arguments.push_back(Utf8FromUtf16(argv[i])); + } + + ::LocalFree(argv); + + return command_line_arguments; +} + +std::string Utf8FromUtf16(const wchar_t* utf16_string) { + if (utf16_string == nullptr) { + return std::string(); + } + unsigned int target_length = ::WideCharToMultiByte( + CP_UTF8, WC_ERR_INVALID_CHARS, utf16_string, + -1, nullptr, 0, nullptr, nullptr) + -1; // remove the trailing null character + int input_length = (int)wcslen(utf16_string); + std::string utf8_string; + if (target_length == 0 || target_length > utf8_string.max_size()) { + return utf8_string; + } + utf8_string.resize(target_length); + int converted_length = ::WideCharToMultiByte( + CP_UTF8, WC_ERR_INVALID_CHARS, utf16_string, + input_length, utf8_string.data(), target_length, nullptr, nullptr); + if (converted_length == 0) { + return std::string(); + } + return utf8_string; +} diff --git a/windows/runner/utils.h b/windows/runner/utils.h new file mode 100644 index 0000000000000000000000000000000000000000..3879d54755798567f0f318d63340508d5668eb96 --- /dev/null +++ b/windows/runner/utils.h @@ -0,0 +1,19 @@ +#ifndef RUNNER_UTILS_H_ +#define RUNNER_UTILS_H_ + +#include +#include + +// Creates a console for the process, and redirects stdout and stderr to +// it for both the runner and the Flutter library. +void CreateAndAttachConsole(); + +// Takes a null-terminated wchar_t* encoded in UTF-16 and returns a std::string +// encoded in UTF-8. Returns an empty std::string on failure. +std::string Utf8FromUtf16(const wchar_t* utf16_string); + +// Gets the command line arguments passed in as a std::vector, +// encoded in UTF-8. Returns an empty std::vector on failure. +std::vector GetCommandLineArguments(); + +#endif // RUNNER_UTILS_H_ diff --git a/windows/runner/win32_window.cpp b/windows/runner/win32_window.cpp new file mode 100644 index 0000000000000000000000000000000000000000..60608d0fe5bff3a7a7e05d5a232944a1a8effe5f --- /dev/null +++ b/windows/runner/win32_window.cpp @@ -0,0 +1,288 @@ +#include "win32_window.h" + +#include +#include + +#include "resource.h" + +namespace { + +/// Window attribute that enables dark mode window decorations. +/// +/// Redefined in case the developer's machine has a Windows SDK older than +/// version 10.0.22000.0. +/// See: https://docs.microsoft.com/windows/win32/api/dwmapi/ne-dwmapi-dwmwindowattribute +#ifndef DWMWA_USE_IMMERSIVE_DARK_MODE +#define DWMWA_USE_IMMERSIVE_DARK_MODE 20 +#endif + +constexpr const wchar_t kWindowClassName[] = L"FLUTTER_RUNNER_WIN32_WINDOW"; + +/// Registry key for app theme preference. +/// +/// A value of 0 indicates apps should use dark mode. A non-zero or missing +/// value indicates apps should use light mode. +constexpr const wchar_t kGetPreferredBrightnessRegKey[] = + L"Software\\Microsoft\\Windows\\CurrentVersion\\Themes\\Personalize"; +constexpr const wchar_t kGetPreferredBrightnessRegValue[] = L"AppsUseLightTheme"; + +// The number of Win32Window objects that currently exist. +static int g_active_window_count = 0; + +using EnableNonClientDpiScaling = BOOL __stdcall(HWND hwnd); + +// Scale helper to convert logical scaler values to physical using passed in +// scale factor +int Scale(int source, double scale_factor) { + return static_cast(source * scale_factor); +} + +// Dynamically loads the |EnableNonClientDpiScaling| from the User32 module. +// This API is only needed for PerMonitor V1 awareness mode. +void EnableFullDpiSupportIfAvailable(HWND hwnd) { + HMODULE user32_module = LoadLibraryA("User32.dll"); + if (!user32_module) { + return; + } + auto enable_non_client_dpi_scaling = + reinterpret_cast( + GetProcAddress(user32_module, "EnableNonClientDpiScaling")); + if (enable_non_client_dpi_scaling != nullptr) { + enable_non_client_dpi_scaling(hwnd); + } + FreeLibrary(user32_module); +} + +} // namespace + +// Manages the Win32Window's window class registration. +class WindowClassRegistrar { + public: + ~WindowClassRegistrar() = default; + + // Returns the singleton registrar instance. + static WindowClassRegistrar* GetInstance() { + if (!instance_) { + instance_ = new WindowClassRegistrar(); + } + return instance_; + } + + // Returns the name of the window class, registering the class if it hasn't + // previously been registered. + const wchar_t* GetWindowClass(); + + // Unregisters the window class. Should only be called if there are no + // instances of the window. + void UnregisterWindowClass(); + + private: + WindowClassRegistrar() = default; + + static WindowClassRegistrar* instance_; + + bool class_registered_ = false; +}; + +WindowClassRegistrar* WindowClassRegistrar::instance_ = nullptr; + +const wchar_t* WindowClassRegistrar::GetWindowClass() { + if (!class_registered_) { + WNDCLASS window_class{}; + window_class.hCursor = LoadCursor(nullptr, IDC_ARROW); + window_class.lpszClassName = kWindowClassName; + window_class.style = CS_HREDRAW | CS_VREDRAW; + window_class.cbClsExtra = 0; + window_class.cbWndExtra = 0; + window_class.hInstance = GetModuleHandle(nullptr); + window_class.hIcon = + LoadIcon(window_class.hInstance, MAKEINTRESOURCE(IDI_APP_ICON)); + window_class.hbrBackground = 0; + window_class.lpszMenuName = nullptr; + window_class.lpfnWndProc = Win32Window::WndProc; + RegisterClass(&window_class); + class_registered_ = true; + } + return kWindowClassName; +} + +void WindowClassRegistrar::UnregisterWindowClass() { + UnregisterClass(kWindowClassName, nullptr); + class_registered_ = false; +} + +Win32Window::Win32Window() { + ++g_active_window_count; +} + +Win32Window::~Win32Window() { + --g_active_window_count; + Destroy(); +} + +bool Win32Window::Create(const std::wstring& title, + const Point& origin, + const Size& size) { + Destroy(); + + const wchar_t* window_class = + WindowClassRegistrar::GetInstance()->GetWindowClass(); + + const POINT target_point = {static_cast(origin.x), + static_cast(origin.y)}; + HMONITOR monitor = MonitorFromPoint(target_point, MONITOR_DEFAULTTONEAREST); + UINT dpi = FlutterDesktopGetDpiForMonitor(monitor); + double scale_factor = dpi / 96.0; + + HWND window = CreateWindow( + window_class, title.c_str(), WS_OVERLAPPEDWINDOW, + Scale(origin.x, scale_factor), Scale(origin.y, scale_factor), + Scale(size.width, scale_factor), Scale(size.height, scale_factor), + nullptr, nullptr, GetModuleHandle(nullptr), this); + + if (!window) { + return false; + } + + UpdateTheme(window); + + return OnCreate(); +} + +bool Win32Window::Show() { + return ShowWindow(window_handle_, SW_SHOWNORMAL); +} + +// static +LRESULT CALLBACK Win32Window::WndProc(HWND const window, + UINT const message, + WPARAM const wparam, + LPARAM const lparam) noexcept { + if (message == WM_NCCREATE) { + auto window_struct = reinterpret_cast(lparam); + SetWindowLongPtr(window, GWLP_USERDATA, + reinterpret_cast(window_struct->lpCreateParams)); + + auto that = static_cast(window_struct->lpCreateParams); + EnableFullDpiSupportIfAvailable(window); + that->window_handle_ = window; + } else if (Win32Window* that = GetThisFromHandle(window)) { + return that->MessageHandler(window, message, wparam, lparam); + } + + return DefWindowProc(window, message, wparam, lparam); +} + +LRESULT +Win32Window::MessageHandler(HWND hwnd, + UINT const message, + WPARAM const wparam, + LPARAM const lparam) noexcept { + switch (message) { + case WM_DESTROY: + window_handle_ = nullptr; + Destroy(); + if (quit_on_close_) { + PostQuitMessage(0); + } + return 0; + + case WM_DPICHANGED: { + auto newRectSize = reinterpret_cast(lparam); + LONG newWidth = newRectSize->right - newRectSize->left; + LONG newHeight = newRectSize->bottom - newRectSize->top; + + SetWindowPos(hwnd, nullptr, newRectSize->left, newRectSize->top, newWidth, + newHeight, SWP_NOZORDER | SWP_NOACTIVATE); + + return 0; + } + case WM_SIZE: { + RECT rect = GetClientArea(); + if (child_content_ != nullptr) { + // Size and position the child window. + MoveWindow(child_content_, rect.left, rect.top, rect.right - rect.left, + rect.bottom - rect.top, TRUE); + } + return 0; + } + + case WM_ACTIVATE: + if (child_content_ != nullptr) { + SetFocus(child_content_); + } + return 0; + + case WM_DWMCOLORIZATIONCOLORCHANGED: + UpdateTheme(hwnd); + return 0; + } + + return DefWindowProc(window_handle_, message, wparam, lparam); +} + +void Win32Window::Destroy() { + OnDestroy(); + + if (window_handle_) { + DestroyWindow(window_handle_); + window_handle_ = nullptr; + } + if (g_active_window_count == 0) { + WindowClassRegistrar::GetInstance()->UnregisterWindowClass(); + } +} + +Win32Window* Win32Window::GetThisFromHandle(HWND const window) noexcept { + return reinterpret_cast( + GetWindowLongPtr(window, GWLP_USERDATA)); +} + +void Win32Window::SetChildContent(HWND content) { + child_content_ = content; + SetParent(content, window_handle_); + RECT frame = GetClientArea(); + + MoveWindow(content, frame.left, frame.top, frame.right - frame.left, + frame.bottom - frame.top, true); + + SetFocus(child_content_); +} + +RECT Win32Window::GetClientArea() { + RECT frame; + GetClientRect(window_handle_, &frame); + return frame; +} + +HWND Win32Window::GetHandle() { + return window_handle_; +} + +void Win32Window::SetQuitOnClose(bool quit_on_close) { + quit_on_close_ = quit_on_close; +} + +bool Win32Window::OnCreate() { + // No-op; provided for subclasses. + return true; +} + +void Win32Window::OnDestroy() { + // No-op; provided for subclasses. +} + +void Win32Window::UpdateTheme(HWND const window) { + DWORD light_mode; + DWORD light_mode_size = sizeof(light_mode); + LSTATUS result = RegGetValue(HKEY_CURRENT_USER, kGetPreferredBrightnessRegKey, + kGetPreferredBrightnessRegValue, + RRF_RT_REG_DWORD, nullptr, &light_mode, + &light_mode_size); + + if (result == ERROR_SUCCESS) { + BOOL enable_dark_mode = light_mode == 0; + DwmSetWindowAttribute(window, DWMWA_USE_IMMERSIVE_DARK_MODE, + &enable_dark_mode, sizeof(enable_dark_mode)); + } +} diff --git a/windows/runner/win32_window.h b/windows/runner/win32_window.h new file mode 100644 index 0000000000000000000000000000000000000000..e901dde684ea8ba25c50ea5dc7d5900da31a30d4 --- /dev/null +++ b/windows/runner/win32_window.h @@ -0,0 +1,102 @@ +#ifndef RUNNER_WIN32_WINDOW_H_ +#define RUNNER_WIN32_WINDOW_H_ + +#include + +#include +#include +#include + +// A class abstraction for a high DPI-aware Win32 Window. Intended to be +// inherited from by classes that wish to specialize with custom +// rendering and input handling +class Win32Window { + public: + struct Point { + unsigned int x; + unsigned int y; + Point(unsigned int x, unsigned int y) : x(x), y(y) {} + }; + + struct Size { + unsigned int width; + unsigned int height; + Size(unsigned int width, unsigned int height) + : width(width), height(height) {} + }; + + Win32Window(); + virtual ~Win32Window(); + + // Creates a win32 window with |title| that is positioned and sized using + // |origin| and |size|. New windows are created on the default monitor. Window + // sizes are specified to the OS in physical pixels, hence to ensure a + // consistent size this function will scale the inputted width and height as + // as appropriate for the default monitor. The window is invisible until + // |Show| is called. Returns true if the window was created successfully. + bool Create(const std::wstring& title, const Point& origin, const Size& size); + + // Show the current window. Returns true if the window was successfully shown. + bool Show(); + + // Release OS resources associated with window. + void Destroy(); + + // Inserts |content| into the window tree. + void SetChildContent(HWND content); + + // Returns the backing Window handle to enable clients to set icon and other + // window properties. Returns nullptr if the window has been destroyed. + HWND GetHandle(); + + // If true, closing this window will quit the application. + void SetQuitOnClose(bool quit_on_close); + + // Return a RECT representing the bounds of the current client area. + RECT GetClientArea(); + + protected: + // Processes and route salient window messages for mouse handling, + // size change and DPI. Delegates handling of these to member overloads that + // inheriting classes can handle. + virtual LRESULT MessageHandler(HWND window, + UINT const message, + WPARAM const wparam, + LPARAM const lparam) noexcept; + + // Called when CreateAndShow is called, allowing subclass window-related + // setup. Subclasses should return false if setup fails. + virtual bool OnCreate(); + + // Called when Destroy is called. + virtual void OnDestroy(); + + private: + friend class WindowClassRegistrar; + + // OS callback called by message pump. Handles the WM_NCCREATE message which + // is passed when the non-client area is being created and enables automatic + // non-client DPI scaling so that the non-client area automatically + // responds to changes in DPI. All other messages are handled by + // MessageHandler. + static LRESULT CALLBACK WndProc(HWND const window, + UINT const message, + WPARAM const wparam, + LPARAM const lparam) noexcept; + + // Retrieves a class instance pointer for |window| + static Win32Window* GetThisFromHandle(HWND const window) noexcept; + + // Update the window frame's theme to match the system theme. + static void UpdateTheme(HWND const window); + + bool quit_on_close_ = false; + + // window handle for top level window. + HWND window_handle_ = nullptr; + + // window handle for hosted content. + HWND child_content_ = nullptr; +}; + +#endif // RUNNER_WIN32_WINDOW_H_