ratio1 3.4.107__tar.gz → 3.4.109__tar.gz

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (230) hide show
  1. {ratio1-3.4.107 → ratio1-3.4.109}/PKG-INFO +1 -1
  2. {ratio1-3.4.107 → ratio1-3.4.109}/pyproject.toml +1 -1
  3. {ratio1-3.4.107 → ratio1-3.4.109}/ratio1/_ver.py +1 -1
  4. {ratio1-3.4.107 → ratio1-3.4.109}/ratio1/cli/cli_commands.py +1 -1
  5. {ratio1-3.4.107 → ratio1-3.4.109}/ratio1/cli/oracles.py +27 -16
  6. ratio1-3.4.109/tutorials/25_cerviguard_war_loopback/cerviguard_test_ui.html +516 -0
  7. ratio1-3.4.109/tutorials/ex24_multi_video_stream_monitor.py +303 -0
  8. ratio1-3.4.109/tutorials/ex25_local_serving_api.py +273 -0
  9. {ratio1-3.4.107 → ratio1-3.4.109}/xperimental/_checks/dauth_check.py +9 -3
  10. {ratio1-3.4.107 → ratio1-3.4.109}/.devcontainer/Dockerfile +0 -0
  11. {ratio1-3.4.107 → ratio1-3.4.109}/.devcontainer/devcontainer.json +0 -0
  12. {ratio1-3.4.107 → ratio1-3.4.109}/.gitattributes +0 -0
  13. {ratio1-3.4.107 → ratio1-3.4.109}/.github/workflows/python-publish.yml +0 -0
  14. {ratio1-3.4.107 → ratio1-3.4.109}/.gitignore +0 -0
  15. {ratio1-3.4.107 → ratio1-3.4.109}/.vscode/launch.json +0 -0
  16. {ratio1-3.4.107 → ratio1-3.4.109}/LICENSE +0 -0
  17. {ratio1-3.4.107 → ratio1-3.4.109}/README.md +0 -0
  18. {ratio1-3.4.107 → ratio1-3.4.109}/TODOs.md +0 -0
  19. {ratio1-3.4.107 → ratio1-3.4.109}/__init__.py +0 -0
  20. {ratio1-3.4.107 → ratio1-3.4.109}/r1ctl.MD +0 -0
  21. {ratio1-3.4.107 → ratio1-3.4.109}/ratio1/__init__.py +0 -0
  22. {ratio1-3.4.107 → ratio1-3.4.109}/ratio1/base/__init__.py +0 -0
  23. {ratio1-3.4.107 → ratio1-3.4.109}/ratio1/base/distributed_custom_code_presets.py +0 -0
  24. {ratio1-3.4.107 → ratio1-3.4.109}/ratio1/base/generic_session.py +0 -0
  25. {ratio1-3.4.107 → ratio1-3.4.109}/ratio1/base/instance.py +0 -0
  26. {ratio1-3.4.107 → ratio1-3.4.109}/ratio1/base/payload/__init__.py +0 -0
  27. {ratio1-3.4.107 → ratio1-3.4.109}/ratio1/base/payload/payload.py +0 -0
  28. {ratio1-3.4.107 → ratio1-3.4.109}/ratio1/base/pipeline.py +0 -0
  29. {ratio1-3.4.107 → ratio1-3.4.109}/ratio1/base/plugin_template.py +0 -0
  30. {ratio1-3.4.107 → ratio1-3.4.109}/ratio1/base/responses.py +0 -0
  31. {ratio1-3.4.107 → ratio1-3.4.109}/ratio1/base/transaction.py +0 -0
  32. {ratio1-3.4.107 → ratio1-3.4.109}/ratio1/base/webapp_pipeline.py +0 -0
  33. {ratio1-3.4.107 → ratio1-3.4.109}/ratio1/base_decentra_object.py +0 -0
  34. {ratio1-3.4.107 → ratio1-3.4.109}/ratio1/bc/__init__.py +0 -0
  35. {ratio1-3.4.107 → ratio1-3.4.109}/ratio1/bc/base.py +0 -0
  36. {ratio1-3.4.107 → ratio1-3.4.109}/ratio1/bc/chain.py +0 -0
  37. {ratio1-3.4.107 → ratio1-3.4.109}/ratio1/bc/ec.py +0 -0
  38. {ratio1-3.4.107 → ratio1-3.4.109}/ratio1/bc/evm.py +0 -0
  39. {ratio1-3.4.107 → ratio1-3.4.109}/ratio1/certs/141.136.35.100.crt +0 -0
  40. {ratio1-3.4.107 → ratio1-3.4.109}/ratio1/certs/195.35.29.4.crt +0 -0
  41. {ratio1-3.4.107 → ratio1-3.4.109}/ratio1/certs/31.97.72.187.crt +0 -0
  42. {ratio1-3.4.107 → ratio1-3.4.109}/ratio1/certs/51.15.142.167.crt +0 -0
  43. {ratio1-3.4.107 → ratio1-3.4.109}/ratio1/certs/72.60.187.24.crt +0 -0
  44. {ratio1-3.4.107 → ratio1-3.4.109}/ratio1/certs/72.60.81.67.crt +0 -0
  45. {ratio1-3.4.107 → ratio1-3.4.109}/ratio1/certs/72.60.83.78.crt +0 -0
  46. {ratio1-3.4.107 → ratio1-3.4.109}/ratio1/certs/__init__.py +0 -0
  47. {ratio1-3.4.107 → ratio1-3.4.109}/ratio1/certs/a0d9818f.ala.eu-central-1.emqxsl.com.crt +0 -0
  48. {ratio1-3.4.107 → ratio1-3.4.109}/ratio1/certs/r9092118.ala.eu-central-1.emqxsl.com.crt +0 -0
  49. {ratio1-3.4.107 → ratio1-3.4.109}/ratio1/certs/s624dbd4.ala.us-east-1.emqxsl.com.crt +0 -0
  50. {ratio1-3.4.107 → ratio1-3.4.109}/ratio1/cli/README.md +0 -0
  51. {ratio1-3.4.107 → ratio1-3.4.109}/ratio1/cli/cli.py +0 -0
  52. {ratio1-3.4.107 → ratio1-3.4.109}/ratio1/cli/nodes.py +0 -0
  53. {ratio1-3.4.107 → ratio1-3.4.109}/ratio1/cli/package_update.py +0 -0
  54. {ratio1-3.4.107 → ratio1-3.4.109}/ratio1/code_cheker/__init__.py +0 -0
  55. {ratio1-3.4.107 → ratio1-3.4.109}/ratio1/code_cheker/base.py +0 -0
  56. {ratio1-3.4.107 → ratio1-3.4.109}/ratio1/code_cheker/checker.py +0 -0
  57. {ratio1-3.4.107 → ratio1-3.4.109}/ratio1/comm/__init__.py +0 -0
  58. {ratio1-3.4.107 → ratio1-3.4.109}/ratio1/comm/amqp_wrapper.py +0 -0
  59. {ratio1-3.4.107 → ratio1-3.4.109}/ratio1/comm/base_comm_wrapper.py +0 -0
  60. {ratio1-3.4.107 → ratio1-3.4.109}/ratio1/comm/mqtt_wrapper.py +0 -0
  61. {ratio1-3.4.107 → ratio1-3.4.109}/ratio1/const/README.md +0 -0
  62. {ratio1-3.4.107 → ratio1-3.4.109}/ratio1/const/__init__.py +0 -0
  63. {ratio1-3.4.107 → ratio1-3.4.109}/ratio1/const/apps.py +0 -0
  64. {ratio1-3.4.107 → ratio1-3.4.109}/ratio1/const/base.py +0 -0
  65. {ratio1-3.4.107 → ratio1-3.4.109}/ratio1/const/comms.py +0 -0
  66. {ratio1-3.4.107 → ratio1-3.4.109}/ratio1/const/environment.py +0 -0
  67. {ratio1-3.4.107 → ratio1-3.4.109}/ratio1/const/evm_net.py +0 -0
  68. {ratio1-3.4.107 → ratio1-3.4.109}/ratio1/const/formatter.py +0 -0
  69. {ratio1-3.4.107 → ratio1-3.4.109}/ratio1/const/heartbeat.py +0 -0
  70. {ratio1-3.4.107 → ratio1-3.4.109}/ratio1/const/misc.py +0 -0
  71. {ratio1-3.4.107 → ratio1-3.4.109}/ratio1/const/payload.py +0 -0
  72. {ratio1-3.4.107 → ratio1-3.4.109}/ratio1/const/plugins/deeploy_const.py +0 -0
  73. {ratio1-3.4.107 → ratio1-3.4.109}/ratio1/default/__init__.py +0 -0
  74. {ratio1-3.4.107 → ratio1-3.4.109}/ratio1/default/instance/__init__.py +0 -0
  75. {ratio1-3.4.107 → ratio1-3.4.109}/ratio1/default/instance/chain_dist_custom_job_01_plugin.py +0 -0
  76. {ratio1-3.4.107 → ratio1-3.4.109}/ratio1/default/instance/custom_webapi_01_plugin.py +0 -0
  77. {ratio1-3.4.107 → ratio1-3.4.109}/ratio1/default/instance/generic_http_01_plugin.py +0 -0
  78. {ratio1-3.4.107 → ratio1-3.4.109}/ratio1/default/instance/net_mon_01_plugin.py +0 -0
  79. {ratio1-3.4.107 → ratio1-3.4.109}/ratio1/default/instance/telegram_basic_bot_01_plugin.py +0 -0
  80. {ratio1-3.4.107 → ratio1-3.4.109}/ratio1/default/instance/telegram_conversational_bot_01_plugin.py +0 -0
  81. {ratio1-3.4.107 → ratio1-3.4.109}/ratio1/default/instance/view_scene_01_plugin.py +0 -0
  82. {ratio1-3.4.107 → ratio1-3.4.109}/ratio1/default/session/mqtt_session.py +0 -0
  83. {ratio1-3.4.107 → ratio1-3.4.109}/ratio1/io_formatter/__init__.py +0 -0
  84. {ratio1-3.4.107 → ratio1-3.4.109}/ratio1/io_formatter/base/__init__.py +0 -0
  85. {ratio1-3.4.107 → ratio1-3.4.109}/ratio1/io_formatter/base/base_formatter.py +0 -0
  86. {ratio1-3.4.107 → ratio1-3.4.109}/ratio1/io_formatter/default/__init__.py +0 -0
  87. {ratio1-3.4.107 → ratio1-3.4.109}/ratio1/io_formatter/default/a_dummy.py +0 -0
  88. {ratio1-3.4.107 → ratio1-3.4.109}/ratio1/io_formatter/default/aixp1.py +0 -0
  89. {ratio1-3.4.107 → ratio1-3.4.109}/ratio1/io_formatter/default/default.py +0 -0
  90. {ratio1-3.4.107 → ratio1-3.4.109}/ratio1/io_formatter/io_formatter_manager.py +0 -0
  91. {ratio1-3.4.107 → ratio1-3.4.109}/ratio1/ipfs/__init__.py +0 -0
  92. {ratio1-3.4.107 → ratio1-3.4.109}/ratio1/ipfs/ifps_keygen +0 -0
  93. {ratio1-3.4.107 → ratio1-3.4.109}/ratio1/ipfs/ipfs_setup/ipfs.service +0 -0
  94. {ratio1-3.4.107 → ratio1-3.4.109}/ratio1/ipfs/ipfs_setup/launch_service.sh +0 -0
  95. {ratio1-3.4.107 → ratio1-3.4.109}/ratio1/ipfs/ipfs_setup/restart.sh +0 -0
  96. {ratio1-3.4.107 → ratio1-3.4.109}/ratio1/ipfs/ipfs_setup/run.sh +0 -0
  97. {ratio1-3.4.107 → ratio1-3.4.109}/ratio1/ipfs/ipfs_setup/setup.sh +0 -0
  98. {ratio1-3.4.107 → ratio1-3.4.109}/ratio1/ipfs/ipfs_setup/show.sh +0 -0
  99. {ratio1-3.4.107 → ratio1-3.4.109}/ratio1/ipfs/ipfs_setup/write_key.sh +0 -0
  100. {ratio1-3.4.107 → ratio1-3.4.109}/ratio1/ipfs/r1fs.py +0 -0
  101. {ratio1-3.4.107 → ratio1-3.4.109}/ratio1/logging/__init__.py +0 -0
  102. {ratio1-3.4.107 → ratio1-3.4.109}/ratio1/logging/base_logger.py +0 -0
  103. {ratio1-3.4.107 → ratio1-3.4.109}/ratio1/logging/logger_mixins/__init__.py +0 -0
  104. {ratio1-3.4.107 → ratio1-3.4.109}/ratio1/logging/logger_mixins/class_instance_mixin.py +0 -0
  105. {ratio1-3.4.107 → ratio1-3.4.109}/ratio1/logging/logger_mixins/computer_vision_mixin.py +0 -0
  106. {ratio1-3.4.107 → ratio1-3.4.109}/ratio1/logging/logger_mixins/datetime_mixin.py +0 -0
  107. {ratio1-3.4.107 → ratio1-3.4.109}/ratio1/logging/logger_mixins/download_mixin.py +0 -0
  108. {ratio1-3.4.107 → ratio1-3.4.109}/ratio1/logging/logger_mixins/general_serialization_mixin.py +0 -0
  109. {ratio1-3.4.107 → ratio1-3.4.109}/ratio1/logging/logger_mixins/json_serialization_mixin.py +0 -0
  110. {ratio1-3.4.107 → ratio1-3.4.109}/ratio1/logging/logger_mixins/machine_mixin.py +0 -0
  111. {ratio1-3.4.107 → ratio1-3.4.109}/ratio1/logging/logger_mixins/pickle_serialization_mixin.py +0 -0
  112. {ratio1-3.4.107 → ratio1-3.4.109}/ratio1/logging/logger_mixins/process_mixin.py +0 -0
  113. {ratio1-3.4.107 → ratio1-3.4.109}/ratio1/logging/logger_mixins/resource_size_mixin.py +0 -0
  114. {ratio1-3.4.107 → ratio1-3.4.109}/ratio1/logging/logger_mixins/timers_mixin.py +0 -0
  115. {ratio1-3.4.107 → ratio1-3.4.109}/ratio1/logging/logger_mixins/upload_mixin.py +0 -0
  116. {ratio1-3.4.107 → ratio1-3.4.109}/ratio1/logging/logger_mixins/utils_mixin.py +0 -0
  117. {ratio1-3.4.107 → ratio1-3.4.109}/ratio1/logging/small_logger.py +0 -0
  118. {ratio1-3.4.107 → ratio1-3.4.109}/ratio1/logging/tzlocal/__init__.py +0 -0
  119. {ratio1-3.4.107 → ratio1-3.4.109}/ratio1/logging/tzlocal/unix.py +0 -0
  120. {ratio1-3.4.107 → ratio1-3.4.109}/ratio1/logging/tzlocal/utils.py +0 -0
  121. {ratio1-3.4.107 → ratio1-3.4.109}/ratio1/logging/tzlocal/win32.py +0 -0
  122. {ratio1-3.4.107 → ratio1-3.4.109}/ratio1/logging/tzlocal/windows_tz.py +0 -0
  123. {ratio1-3.4.107 → ratio1-3.4.109}/ratio1/plugins_manager_mixin.py +0 -0
  124. {ratio1-3.4.107 → ratio1-3.4.109}/ratio1/utils/__init__.py +0 -0
  125. {ratio1-3.4.107 → ratio1-3.4.109}/ratio1/utils/comm_utils.py +0 -0
  126. {ratio1-3.4.107 → ratio1-3.4.109}/ratio1/utils/config.py +0 -0
  127. {ratio1-3.4.107 → ratio1-3.4.109}/ratio1/utils/dotenv.py +0 -0
  128. {ratio1-3.4.107 → ratio1-3.4.109}/ratio1/utils/oracle_sync/oracle_tester.py +0 -0
  129. {ratio1-3.4.107 → ratio1-3.4.109}/requirements.txt +0 -0
  130. {ratio1-3.4.107 → ratio1-3.4.109}/template.env +0 -0
  131. {ratio1-3.4.107 → ratio1-3.4.109}/tutorials/.example_env +0 -0
  132. {ratio1-3.4.107 → ratio1-3.4.109}/tutorials/8. custom_code_fastapi_assets/index.html +0 -0
  133. {ratio1-3.4.107 → ratio1-3.4.109}/tutorials/9. code_sandbox_from_scratch_assets/index.html +0 -0
  134. {ratio1-3.4.107 → ratio1-3.4.109}/tutorials/_example_pk_sdk.pem +0 -0
  135. {ratio1-3.4.107 → ratio1-3.4.109}/tutorials/eth2025/deploy_home_safety.py +0 -0
  136. {ratio1-3.4.107 → ratio1-3.4.109}/tutorials/eth2025/deploy_maintenance_monitoring.py +0 -0
  137. {ratio1-3.4.107 → ratio1-3.4.109}/tutorials/ex01_part1_connect.py +0 -0
  138. {ratio1-3.4.107 → ratio1-3.4.109}/tutorials/ex01_part2_filter.py +0 -0
  139. {ratio1-3.4.107 → ratio1-3.4.109}/tutorials/ex01_part3_adv_filter.py +0 -0
  140. {ratio1-3.4.107 → ratio1-3.4.109}/tutorials/ex02_part1_deploy_webapi.py +0 -0
  141. {ratio1-3.4.107 → ratio1-3.4.109}/tutorials/ex02_part2_deploy_plugin.py +0 -0
  142. {ratio1-3.4.107 → ratio1-3.4.109}/tutorials/ex02_part3_deploy_r1fs_test.py +0 -0
  143. {ratio1-3.4.107 → ratio1-3.4.109}/tutorials/ex03_custom_code_on_one_remote__example_1.py +0 -0
  144. {ratio1-3.4.107 → ratio1-3.4.109}/tutorials/ex04_custom_code_on_one_remote__example_2.py +0 -0
  145. {ratio1-3.4.107 → ratio1-3.4.109}/tutorials/ex05_custom_code_on_one_remote__example_3.py +0 -0
  146. {ratio1-3.4.107 → ratio1-3.4.109}/tutorials/ex06_custom_code_on_multiple_remotes__example_1.py +0 -0
  147. {ratio1-3.4.107 → ratio1-3.4.109}/tutorials/ex07_custom_code_on_multiple_remotes__example_2.py +0 -0
  148. {ratio1-3.4.107 → ratio1-3.4.109}/tutorials/ex08_custom_webapi.py +0 -0
  149. {ratio1-3.4.107 → ratio1-3.4.109}/tutorials/ex09_code_sandbox_from_scratch.py +0 -0
  150. {ratio1-3.4.107 → ratio1-3.4.109}/tutorials/ex10_telegram_echo_bot.py +0 -0
  151. {ratio1-3.4.107 → ratio1-3.4.109}/tutorials/ex11_telegram_blackjack_bot.py +0 -0
  152. {ratio1-3.4.107 → ratio1-3.4.109}/tutorials/ex12_telegram_smart_bot.py +0 -0
  153. {ratio1-3.4.107 → ratio1-3.4.109}/tutorials/ex13_launch_repo_based_webapp.py +0 -0
  154. {ratio1-3.4.107 → ratio1-3.4.109}/tutorials/ex14_wallets.py +0 -0
  155. {ratio1-3.4.107 → ratio1-3.4.109}/tutorials/ex15_telegram_rogue_style_game.py +0 -0
  156. {ratio1-3.4.107 → ratio1-3.4.109}/tutorials/ex16_launch_repo_based_http_server.py +0 -0
  157. {ratio1-3.4.107 → ratio1-3.4.109}/tutorials/ex17_launch_repo_based_balanced_webapp.py +0 -0
  158. {ratio1-3.4.107 → ratio1-3.4.109}/tutorials/ex18_deploy_container_webapi.py +0 -0
  159. {ratio1-3.4.107 → ratio1-3.4.109}/tutorials/ex19_deeploy_container_example.py +0 -0
  160. {ratio1-3.4.107 → ratio1-3.4.109}/tutorials/ex20_deeploy_telegram_bot.py +0 -0
  161. {ratio1-3.4.107 → ratio1-3.4.109}/tutorials/ex21_telegram_community_bot.py +0 -0
  162. {ratio1-3.4.107 → ratio1-3.4.109}/tutorials/ex22_deeploy_custom_code.py +0 -0
  163. {ratio1-3.4.107 → ratio1-3.4.109}/tutorials/ex23_deploy_worker_app.py +0 -0
  164. {ratio1-3.4.107 → ratio1-3.4.109}/tutorials/video_presentation/1. hello_world.ipynb +0 -0
  165. {ratio1-3.4.107 → ratio1-3.4.109}/winrun.bat +0 -0
  166. {ratio1-3.4.107 → ratio1-3.4.109}/xperimental/README.md +0 -0
  167. {ratio1-3.4.107 → ratio1-3.4.109}/xperimental/_checks/_show_config_check.py +0 -0
  168. {ratio1-3.4.107 → ratio1-3.4.109}/xperimental/_checks/cstore_check.py +0 -0
  169. {ratio1-3.4.107 → ratio1-3.4.109}/xperimental/_checks/keys_check.py +0 -0
  170. {ratio1-3.4.107 → ratio1-3.4.109}/xperimental/_checks/node_info_check.py +0 -0
  171. {ratio1-3.4.107 → ratio1-3.4.109}/xperimental/_checks/ora_check.py +0 -0
  172. {ratio1-3.4.107 → ratio1-3.4.109}/xperimental/_checks/ora_intervals.py +0 -0
  173. {ratio1-3.4.107 → ratio1-3.4.109}/xperimental/_checks/ora_sign_check.py +0 -0
  174. {ratio1-3.4.107 → ratio1-3.4.109}/xperimental/_checks/owner_check.py +0 -0
  175. {ratio1-3.4.107 → ratio1-3.4.109}/xperimental/_checks/payload_check.py +0 -0
  176. {ratio1-3.4.107 → ratio1-3.4.109}/xperimental/_checks/session_check.py +0 -0
  177. {ratio1-3.4.107 → ratio1-3.4.109}/xperimental/_checks/w3_all_active_jobs_check.py +0 -0
  178. {ratio1-3.4.107 → ratio1-3.4.109}/xperimental/_checks/w3_auth_check.py +0 -0
  179. {ratio1-3.4.107 → ratio1-3.4.109}/xperimental/_checks/w3_first_closable_job_check.py +0 -0
  180. {ratio1-3.4.107 → ratio1-3.4.109}/xperimental/_checks/w3_nodes_licenses.py +0 -0
  181. {ratio1-3.4.107 → ratio1-3.4.109}/xperimental/_checks/w3_oracles_check.py +0 -0
  182. {ratio1-3.4.107 → ratio1-3.4.109}/xperimental/_checks/w3_poai_check.py +0 -0
  183. {ratio1-3.4.107 → ratio1-3.4.109}/xperimental/_checks/whitelist_check.py +0 -0
  184. {ratio1-3.4.107 → ratio1-3.4.109}/xperimental/_checks/workload_check.py +0 -0
  185. {ratio1-3.4.107 → ratio1-3.4.109}/xperimental/ai4e/delete.py +0 -0
  186. {ratio1-3.4.107 → ratio1-3.4.109}/xperimental/ai4e/launcher.py +0 -0
  187. {ratio1-3.4.107 → ratio1-3.4.109}/xperimental/dates/check_date.py +0 -0
  188. {ratio1-3.4.107 → ratio1-3.4.109}/xperimental/debug/close_pipeline.py +0 -0
  189. {ratio1-3.4.107 → ratio1-3.4.109}/xperimental/decentralized/chain_dist_example.py +0 -0
  190. {ratio1-3.4.107 → ratio1-3.4.109}/xperimental/decentralized/chain_dist_example_initiator.py +0 -0
  191. {ratio1-3.4.107 → ratio1-3.4.109}/xperimental/decentralized/chain_dist_example_worker.py +0 -0
  192. {ratio1-3.4.107 → ratio1-3.4.109}/xperimental/deeploy/checker.py +0 -0
  193. {ratio1-3.4.107 → ratio1-3.4.109}/xperimental/deeploy/checker2.py +0 -0
  194. {ratio1-3.4.107 → ratio1-3.4.109}/xperimental/deeploy/create_request.py +0 -0
  195. {ratio1-3.4.107 → ratio1-3.4.109}/xperimental/enc_dec/enc_dec_test.py +0 -0
  196. {ratio1-3.4.107 → ratio1-3.4.109}/xperimental/eth/allocate_rewards.py +0 -0
  197. {ratio1-3.4.107 → ratio1-3.4.109}/xperimental/eth/balance.py +0 -0
  198. {ratio1-3.4.107 → ratio1-3.4.109}/xperimental/eth/eth_sign.py +0 -0
  199. {ratio1-3.4.107 → ratio1-3.4.109}/xperimental/eth/info.md +0 -0
  200. {ratio1-3.4.107 → ratio1-3.4.109}/xperimental/eth/send.py +0 -0
  201. {ratio1-3.4.107 → ratio1-3.4.109}/xperimental/eth/send_many.py +0 -0
  202. {ratio1-3.4.107 → ratio1-3.4.109}/xperimental/eth/sign.py +0 -0
  203. {ratio1-3.4.107 → ratio1-3.4.109}/xperimental/log.py +0 -0
  204. {ratio1-3.4.107 → ratio1-3.4.109}/xperimental/logger/run.py +0 -0
  205. {ratio1-3.4.107 → ratio1-3.4.109}/xperimental/lp/lp_checker.py +0 -0
  206. {ratio1-3.4.107 → ratio1-3.4.109}/xperimental/multi-enc-dec/multi_test1.py +0 -0
  207. {ratio1-3.4.107 → ratio1-3.4.109}/xperimental/multi-enc-dec/multi_test2.py +0 -0
  208. {ratio1-3.4.107 → ratio1-3.4.109}/xperimental/netmon/check_netmon.py +0 -0
  209. {ratio1-3.4.107 → ratio1-3.4.109}/xperimental/netmon/netmon_data.json +0 -0
  210. {ratio1-3.4.107 → ratio1-3.4.109}/xperimental/pipelines/start.py +0 -0
  211. {ratio1-3.4.107 → ratio1-3.4.109}/xperimental/pipelines/stop.py +0 -0
  212. {ratio1-3.4.107 → ratio1-3.4.109}/xperimental/scripts/monitoring/collect_messages.py +0 -0
  213. {ratio1-3.4.107 → ratio1-3.4.109}/xperimental/scripts/monitoring/get_hb_distribution.py +0 -0
  214. {ratio1-3.4.107 → ratio1-3.4.109}/xperimental/scripts/monitoring/multithreaded_network_sniffer.py +0 -0
  215. {ratio1-3.4.107 → ratio1-3.4.109}/xperimental/sign/simple_payload_checker.py +0 -0
  216. {ratio1-3.4.107 → ratio1-3.4.109}/xperimental/sign/test_sign1.py +0 -0
  217. {ratio1-3.4.107 → ratio1-3.4.109}/xperimental/sign/test_sign2.py +0 -0
  218. {ratio1-3.4.107 → ratio1-3.4.109}/xperimental/test.py +0 -0
  219. {ratio1-3.4.107 → ratio1-3.4.109}/xperimental/tokens/get_check.py +0 -0
  220. {ratio1-3.4.107 → ratio1-3.4.109}/xperimental/utils/get_documentation.py +0 -0
  221. {ratio1-3.4.107 → ratio1-3.4.109}/xperimental/various/attach_example.py +0 -0
  222. {ratio1-3.4.107 → ratio1-3.4.109}/xperimental/various/ex1.py +0 -0
  223. {ratio1-3.4.107 → ratio1-3.4.109}/xperimental/various/hello.py +0 -0
  224. {ratio1-3.4.107 → ratio1-3.4.109}/xperimental/various/remote_exec.py +0 -0
  225. {ratio1-3.4.107 → ratio1-3.4.109}/xperimental/various/save_images.py +0 -0
  226. {ratio1-3.4.107 → ratio1-3.4.109}/xperimental/wl/wl_add.py +0 -0
  227. {ratio1-3.4.107 → ratio1-3.4.109}/xperimental/xarchive/_tutorials/3. simple_real_time_custom_code.py +0 -0
  228. {ratio1-3.4.107 → ratio1-3.4.109}/xperimental/xarchive/_tutorials/4. real_time_custom_code_2.py +0 -0
  229. {ratio1-3.4.107 → ratio1-3.4.109}/xperimental/xarchive/_tutorials/8. chatbot.py +0 -0
  230. {ratio1-3.4.107 → ratio1-3.4.109}/xperimental/xarchive/test.py +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: ratio1
3
- Version: 3.4.107
3
+ Version: 3.4.109
4
4
  Summary: `ratio1` or Ration1 SDK is the Python SDK required for client app development for the Ratio1 ecosystem
5
5
  Project-URL: Homepage, https://github.com/Ratio1/ratio1_sdk
6
6
  Project-URL: Bug Tracker, https://github.com/Ratio1/ratio1_sdk/issues
@@ -4,7 +4,7 @@ build-backend = "hatchling.build"
4
4
 
5
5
  [project]
6
6
  name = "ratio1"
7
- version = "3.4.107"
7
+ version = "3.4.109"
8
8
  authors = [
9
9
  { name="Andrei Ionut Damian", email="andrei.damian@ratio1.ai" },
10
10
  { name="Cristan Bleotiu", email="cristian.bleotiu@ratio1.ai" },
@@ -1,4 +1,4 @@
1
- __VER__ = "3.4.107"
1
+ __VER__ = "3.4.109"
2
2
 
3
3
  if __name__ == "__main__":
4
4
  with open("pyproject.toml", "rt") as fd:
@@ -149,7 +149,7 @@ CLI_COMMANDS = {
149
149
  "--skip-seeds": "Skip the seed nodes in the rollout (flag)",
150
150
  "--skip-oracles": "Skip the oracle nodes in the rollout (flag)",
151
151
  "--skip-workers": "Skip the remaining edge worker nodes in the rollout (flag)",
152
- "--no-timeout": "Do not wait between nodes restarts (flag)",
152
+ "--timeout": "Wait between worker nodes restarts (flag)",
153
153
  }
154
154
  },
155
155
  "inspect": {
@@ -222,13 +222,13 @@ if True:
222
222
  skip_seeds = args.skip_seeds
223
223
  skip_oracles = args.skip_oracles
224
224
  skip_workers = getattr(args, "skip_workers", False)
225
- no_timeout = args.no_timeout
225
+ no_timeout = not args.timeout
226
226
  run_seed_nodes = not skip_seeds
227
227
  run_oracle_nodes = not skip_oracles
228
228
  run_edge_nodes = not skip_workers
229
229
 
230
230
  # Adjust these values to tweak pauses and restart pacing across node groups.
231
- pause_after_seed_seconds = 60
231
+ pause_after_seed_seconds = 120
232
232
  pause_after_oracle_seconds = 60
233
233
  worker_timeout_min_seconds = 5
234
234
  worker_timeout_max_seconds = 25
@@ -255,11 +255,11 @@ if True:
255
255
  log_with_color("======================================================", color='b')
256
256
  log_with_color("Starting Oracle Rollout...", color='g')
257
257
  log_with_color("======================================================", color='b')
258
+
258
259
  session = Session(
259
260
  silent=True
260
261
  )
261
262
  current_network = session.bc_engine.current_evm_network
262
- session.close()
263
263
 
264
264
  restart_plan_display = " -> ".join(restart_groups)
265
265
  confirmation_keyword = "RESTART ALL" if len(restart_groups) == 3 else f"RESTART {', '.join(restart_groups)}"
@@ -282,11 +282,11 @@ if True:
282
282
  log_with_color("Aborted by user...", color='y')
283
283
  return
284
284
 
285
- session = Session(
286
- silent=silent
287
- )
285
+ session.log.silent = silent
286
+ session.silent = silent
288
287
 
289
288
  seed_nodes_addresses = _get_seed_nodes(current_network)
289
+ seed_nodes_aliases = [session.get_node_alias(addr) for addr in seed_nodes_addresses]
290
290
 
291
291
  all_online_nodes = _get_all_online_nodes()
292
292
  remaining_nodes = [
@@ -301,25 +301,36 @@ if True:
301
301
 
302
302
  if run_seed_nodes:
303
303
  # 1. Send restart command to Seed Nodes.
304
- log_with_color(f"Sending restart commands to {len(seed_nodes_addresses)} seed nodes: {seed_nodes_addresses}",
305
- color='b')
304
+ log_with_color(
305
+ f"Sending restart commands to {len(seed_nodes_addresses)} seed nodes: {seed_nodes_aliases}",
306
+ color='b'
307
+ )
306
308
  _send_restart_command(session=session, nodes=seed_nodes_addresses)
309
+
310
+ # now check heartbeats for SHUTDOWN confirmation individually
311
+ # ... we display one by one the status with timeout `pause_after_seed_seconds`
312
+ # here all seeds restarted so we check recent heartbeats for each of them
313
+ # ... we display one by one the status with timeout `pause_after_seed_seconds`
314
+ # now finally we confirm all seeds are back online
307
315
  restarted_seed_nodes_count = len(seed_nodes_addresses)
308
316
 
309
317
  # Remove seed node addresses from all_nodes_addresses
310
318
  if run_oracle_nodes or run_edge_nodes:
311
319
  if pause_after_seed_seconds > 0:
312
320
  log_with_color(
313
- f"Seed nodes restarted. Waiting {pause_after_seed_seconds} seconds before sending restart commands to the next group of nodes.",
314
- color='g')
315
- sleep(pause_after_seed_seconds)
321
+ f"Seed nodes restarting. Waiting {pause_after_seed_seconds} seconds before sending restart commands to the next group of nodes.",
322
+ color='g'
323
+ )
324
+ sleep(pause_after_seed_seconds) # maybe obsolete due to per-node wait above
316
325
  else:
317
326
  log_with_color(
318
- "Seed nodes restarted. Continuing without wait before the next group of nodes.",
319
- color='g')
327
+ "Seed nodes restarting. Continuing without wait before the next group of nodes.",
328
+ color='g'
329
+ )
320
330
  else:
321
331
  log_with_color("Skipping Seed Nodes restart as per user request.", color='y')
322
-
332
+
333
+
323
334
  # 2. Send restart commands to all Oracle nodes, except seed nodes.
324
335
  oracle_nodes_addresses = [
325
336
  node['address']
@@ -330,8 +341,8 @@ if True:
330
341
  if run_oracle_nodes:
331
342
  log_with_color(
332
343
  f"Sending restart commands to {len(oracle_nodes_addresses)} Non-Seed Oracle nodes, except seed nodes: {remaining_nodes}",
333
- color='b')
334
-
344
+ color='b'
345
+ )
335
346
  _send_restart_command(session=session, nodes=oracle_nodes_addresses)
336
347
  restarted_oracle_nodes_count = len(oracle_nodes_addresses)
337
348
  if run_edge_nodes:
@@ -0,0 +1,516 @@
1
+ <!DOCTYPE html>
2
+ <html lang="en">
3
+ <head>
4
+ <meta charset="UTF-8">
5
+ <meta name="viewport" content="width=device-width, initial-scale=1.0">
6
+ <title>CerviGuard WAR - Test UI</title>
7
+ <style>
8
+ * {
9
+ margin: 0;
10
+ padding: 0;
11
+ box-sizing: border-box;
12
+ }
13
+
14
+ body {
15
+ font-family: 'Segoe UI', Tahoma, Geneva, Verdana, sans-serif;
16
+ background: linear-gradient(135deg, #667eea 0%, #764ba2 100%);
17
+ min-height: 100vh;
18
+ padding: 20px;
19
+ }
20
+
21
+ .container {
22
+ max-width: 900px;
23
+ margin: 0 auto;
24
+ background: white;
25
+ border-radius: 15px;
26
+ box-shadow: 0 20px 60px rgba(0,0,0,0.3);
27
+ padding: 40px;
28
+ }
29
+
30
+ h1 {
31
+ color: #667eea;
32
+ text-align: center;
33
+ margin-bottom: 10px;
34
+ font-size: 2.5em;
35
+ }
36
+
37
+ .subtitle {
38
+ text-align: center;
39
+ color: #666;
40
+ margin-bottom: 30px;
41
+ font-size: 1.1em;
42
+ }
43
+
44
+ .api-config {
45
+ background: #f8f9fa;
46
+ padding: 15px;
47
+ border-radius: 8px;
48
+ margin-bottom: 30px;
49
+ }
50
+
51
+ .api-config label {
52
+ display: block;
53
+ margin-bottom: 5px;
54
+ color: #333;
55
+ font-weight: 600;
56
+ }
57
+
58
+ .api-config input {
59
+ width: 100%;
60
+ padding: 10px;
61
+ border: 2px solid #ddd;
62
+ border-radius: 5px;
63
+ font-size: 14px;
64
+ }
65
+
66
+ .upload-section {
67
+ border: 3px dashed #667eea;
68
+ border-radius: 10px;
69
+ padding: 40px;
70
+ text-align: center;
71
+ margin-bottom: 30px;
72
+ background: #f8f9ff;
73
+ cursor: pointer;
74
+ transition: all 0.3s;
75
+ }
76
+
77
+ .upload-section:hover {
78
+ background: #e8edff;
79
+ border-color: #764ba2;
80
+ }
81
+
82
+ .upload-section.dragover {
83
+ background: #d0d9ff;
84
+ border-color: #764ba2;
85
+ }
86
+
87
+ #imageInput {
88
+ display: none;
89
+ }
90
+
91
+ .btn {
92
+ background: linear-gradient(135deg, #667eea 0%, #764ba2 100%);
93
+ color: white;
94
+ border: none;
95
+ padding: 12px 30px;
96
+ border-radius: 25px;
97
+ font-size: 16px;
98
+ font-weight: 600;
99
+ cursor: pointer;
100
+ transition: transform 0.2s;
101
+ margin: 5px;
102
+ }
103
+
104
+ .btn:hover {
105
+ transform: translateY(-2px);
106
+ box-shadow: 0 5px 15px rgba(102, 126, 234, 0.4);
107
+ }
108
+
109
+ .btn:active {
110
+ transform: translateY(0);
111
+ }
112
+
113
+ .btn:disabled {
114
+ opacity: 0.5;
115
+ cursor: not-allowed;
116
+ }
117
+
118
+ #preview {
119
+ max-width: 100%;
120
+ max-height: 300px;
121
+ margin: 20px auto;
122
+ display: none;
123
+ border-radius: 10px;
124
+ box-shadow: 0 5px 15px rgba(0,0,0,0.2);
125
+ }
126
+
127
+ .status {
128
+ padding: 15px;
129
+ border-radius: 8px;
130
+ margin: 10px 0;
131
+ font-weight: 500;
132
+ }
133
+
134
+ .status.info {
135
+ background: #d1ecf1;
136
+ color: #0c5460;
137
+ border: 1px solid #bee5eb;
138
+ }
139
+
140
+ .status.success {
141
+ background: #d4edda;
142
+ color: #155724;
143
+ border: 1px solid #c3e6cb;
144
+ }
145
+
146
+ .status.error {
147
+ background: #f8d7da;
148
+ color: #721c24;
149
+ border: 1px solid #f5c6cb;
150
+ }
151
+
152
+ .status.processing {
153
+ background: #fff3cd;
154
+ color: #856404;
155
+ border: 1px solid #ffeeba;
156
+ }
157
+
158
+ .results {
159
+ background: #f8f9fa;
160
+ padding: 20px;
161
+ border-radius: 10px;
162
+ margin-top: 20px;
163
+ display: none;
164
+ }
165
+
166
+ .results h3 {
167
+ color: #667eea;
168
+ margin-bottom: 15px;
169
+ }
170
+
171
+ .result-item {
172
+ padding: 10px;
173
+ margin: 5px 0;
174
+ background: white;
175
+ border-radius: 5px;
176
+ display: flex;
177
+ justify-content: space-between;
178
+ }
179
+
180
+ .result-label {
181
+ font-weight: 600;
182
+ color: #333;
183
+ }
184
+
185
+ .result-value {
186
+ color: #667eea;
187
+ font-family: 'Courier New', monospace;
188
+ }
189
+
190
+ .loader {
191
+ border: 4px solid #f3f3f3;
192
+ border-top: 4px solid #667eea;
193
+ border-radius: 50%;
194
+ width: 40px;
195
+ height: 40px;
196
+ animation: spin 1s linear infinite;
197
+ margin: 20px auto;
198
+ display: none;
199
+ }
200
+
201
+ @keyframes spin {
202
+ 0% { transform: rotate(0deg); }
203
+ 100% { transform: rotate(360deg); }
204
+ }
205
+
206
+ .footer {
207
+ text-align: center;
208
+ margin-top: 30px;
209
+ color: #666;
210
+ font-size: 14px;
211
+ }
212
+
213
+ .loopback-indicator {
214
+ background: #667eea;
215
+ color: white;
216
+ padding: 10px 20px;
217
+ border-radius: 25px;
218
+ display: inline-block;
219
+ margin: 20px 0;
220
+ font-weight: 600;
221
+ }
222
+ </style>
223
+ </head>
224
+ <body>
225
+ <div class="container">
226
+ <h1>🔬 CerviGuard WAR</h1>
227
+ <p class="subtitle">Cervical Image Analysis - Loopback Pipeline Test</p>
228
+
229
+ <div style="text-align: center;">
230
+ <span class="loopback-indicator">🔄 LOOPBACK MODE ENABLED</span>
231
+ </div>
232
+
233
+ <!-- API Configuration -->
234
+ <div class="api-config">
235
+ <label for="apiUrl">API Base URL:</label>
236
+ <input type="text" id="apiUrl" value="http://localhost:5002" placeholder="http://localhost:5002">
237
+ </div>
238
+
239
+ <!-- Upload Section -->
240
+ <div class="upload-section" id="uploadZone">
241
+ <h3>📤 Upload Cervical Image</h3>
242
+ <p>Click to select or drag and drop an image here</p>
243
+ <p style="font-size: 12px; color: #666; margin-top: 10px;">Supported: PNG, JPG, JPEG</p>
244
+ <input type="file" id="imageInput" accept="image/*">
245
+ </div>
246
+
247
+ <!-- Image Preview -->
248
+ <img id="preview" alt="Image preview">
249
+
250
+ <!-- Action Buttons -->
251
+ <div style="text-align: center; margin: 20px 0;">
252
+ <button class="btn" id="submitBtn" disabled>Submit Image for Analysis</button>
253
+ <button class="btn" id="checkStatusBtn" style="background: linear-gradient(135deg, #11998e 0%, #38ef7d 100%);">
254
+ Check System Status
255
+ </button>
256
+ </div>
257
+
258
+ <!-- Loader -->
259
+ <div class="loader" id="loader"></div>
260
+
261
+ <!-- Status Messages -->
262
+ <div id="statusContainer"></div>
263
+
264
+ <!-- Results -->
265
+ <div class="results" id="resultsContainer">
266
+ <h3>📊 Analysis Results</h3>
267
+ <div id="resultsContent"></div>
268
+ </div>
269
+
270
+ <!-- Footer -->
271
+ <div class="footer">
272
+ <p>CerviGuard WAR Test Interface | Naeural Edge Node Loopback Demo</p>
273
+ <p style="font-size: 12px; margin-top: 5px;">
274
+ Flow: UI → API (localhost) → Loopback Queue → Processor → Results
275
+ </p>
276
+ </div>
277
+ </div>
278
+
279
+ <script>
280
+ const uploadZone = document.getElementById('uploadZone');
281
+ const imageInput = document.getElementById('imageInput');
282
+ const preview = document.getElementById('preview');
283
+ const submitBtn = document.getElementById('submitBtn');
284
+ const checkStatusBtn = document.getElementById('checkStatusBtn');
285
+ const loader = document.getElementById('loader');
286
+ const statusContainer = document.getElementById('statusContainer');
287
+ const resultsContainer = document.getElementById('resultsContainer');
288
+ const resultsContent = document.getElementById('resultsContent');
289
+ const apiUrlInput = document.getElementById('apiUrl');
290
+
291
+ let selectedImage = null;
292
+ let currentRequestId = null;
293
+
294
+ // Upload zone click
295
+ uploadZone.addEventListener('click', () => imageInput.click());
296
+
297
+ // Drag and drop
298
+ uploadZone.addEventListener('dragover', (e) => {
299
+ e.preventDefault();
300
+ uploadZone.classList.add('dragover');
301
+ });
302
+
303
+ uploadZone.addEventListener('dragleave', () => {
304
+ uploadZone.classList.remove('dragover');
305
+ });
306
+
307
+ uploadZone.addEventListener('drop', (e) => {
308
+ e.preventDefault();
309
+ uploadZone.classList.remove('dragover');
310
+ const files = e.dataTransfer.files;
311
+ if (files.length > 0) {
312
+ handleImageSelect(files[0]);
313
+ }
314
+ });
315
+
316
+ // File input change
317
+ imageInput.addEventListener('change', (e) => {
318
+ if (e.target.files.length > 0) {
319
+ handleImageSelect(e.target.files[0]);
320
+ }
321
+ });
322
+
323
+ // Handle image selection
324
+ function handleImageSelect(file) {
325
+ if (!file.type.startsWith('image/')) {
326
+ showStatus('Please select a valid image file', 'error');
327
+ return;
328
+ }
329
+
330
+ const reader = new FileReader();
331
+ reader.onload = (e) => {
332
+ selectedImage = e.target.result;
333
+ preview.src = selectedImage;
334
+ preview.style.display = 'block';
335
+ submitBtn.disabled = false;
336
+ showStatus(`Image loaded: ${file.name} (${(file.size / 1024).toFixed(2)} KB)`, 'info');
337
+ };
338
+ reader.readAsDataURL(file);
339
+ }
340
+
341
+ // Submit image
342
+ submitBtn.addEventListener('click', async () => {
343
+ if (!selectedImage) return;
344
+
345
+ submitBtn.disabled = true;
346
+ loader.style.display = 'block';
347
+ resultsContainer.style.display = 'none';
348
+
349
+ // Extract base64 data (remove data URL prefix)
350
+ const base64Data = selectedImage.split(',')[1];
351
+
352
+ const apiUrl = apiUrlInput.value;
353
+
354
+ try {
355
+ showStatus('Submitting image to CerviGuard API...', 'processing');
356
+
357
+ const response = await fetch(`${apiUrl}/cerviguard_submit_image`, {
358
+ method: 'POST',
359
+ headers: {
360
+ 'Content-Type': 'application/json',
361
+ },
362
+ body: JSON.stringify({
363
+ image_data: base64Data,
364
+ metadata: {
365
+ source: 'test_ui',
366
+ timestamp: new Date().toISOString()
367
+ }
368
+ })
369
+ });
370
+
371
+ const data = await response.json();
372
+ const result = data.result;
373
+
374
+ if (result.status === 'submitted') {
375
+ currentRequestId = result.request_id;
376
+ showStatus(`Image submitted successfully! Request ID: ${currentRequestId}`, 'success');
377
+ showStatus('Polling for results (loopback processing)...', 'processing');
378
+ pollForResults(currentRequestId);
379
+ } else {
380
+ showStatus(`Error: ${result.error || 'Unknown error'}`, 'error');
381
+ loader.style.display = 'none';
382
+ submitBtn.disabled = false;
383
+ }
384
+
385
+ } catch (error) {
386
+ showStatus(`Network Error: ${error.message}`, 'error');
387
+ showStatus('Make sure the API is running on the specified URL', 'error');
388
+ loader.style.display = 'none';
389
+ submitBtn.disabled = false;
390
+ }
391
+ });
392
+
393
+ // Poll for results
394
+ async function pollForResults(requestId, attempt = 1, maxAttempts = 20) {
395
+ const apiUrl = apiUrlInput.value;
396
+
397
+ try {
398
+ const response = await fetch(`${apiUrl}/cerviguard_get_result?request_id=${requestId}`);
399
+ const data = await response.json();
400
+ const result = data.result;
401
+
402
+ if (result.status === 'completed') {
403
+ loader.style.display = 'none';
404
+ showStatus('✓ Processing completed successfully!', 'success');
405
+ displayResults(result.result);
406
+ submitBtn.disabled = false;
407
+ } else if (result.status === 'processing') {
408
+ showStatus(`⏳ Processing... (attempt ${attempt}/${maxAttempts})`, 'processing');
409
+ if (attempt < maxAttempts) {
410
+ setTimeout(() => pollForResults(requestId, attempt + 1, maxAttempts), 1000);
411
+ } else {
412
+ loader.style.display = 'none';
413
+ showStatus('Timeout: Processing is taking too long', 'error');
414
+ submitBtn.disabled = false;
415
+ }
416
+ } else if (result.status === 'error') {
417
+ loader.style.display = 'none';
418
+ showStatus(`✗ Processing Error: ${result.error}`, 'error');
419
+ submitBtn.disabled = false;
420
+ } else {
421
+ loader.style.display = 'none';
422
+ showStatus(`Unknown status: ${result.status}`, 'error');
423
+ submitBtn.disabled = false;
424
+ }
425
+
426
+ } catch (error) {
427
+ loader.style.display = 'none';
428
+ showStatus(`Polling Error: ${error.message}`, 'error');
429
+ submitBtn.disabled = false;
430
+ }
431
+ }
432
+
433
+ // Display results
434
+ function displayResults(result) {
435
+ const imgInfo = result.image_info;
436
+
437
+ resultsContent.innerHTML = `
438
+ <div class="result-item">
439
+ <span class="result-label">Width:</span>
440
+ <span class="result-value">${imgInfo.width} pixels</span>
441
+ </div>
442
+ <div class="result-item">
443
+ <span class="result-label">Height:</span>
444
+ <span class="result-value">${imgInfo.height} pixels</span>
445
+ </div>
446
+ <div class="result-item">
447
+ <span class="result-label">Channels:</span>
448
+ <span class="result-value">${imgInfo.channels}</span>
449
+ </div>
450
+ <div class="result-item">
451
+ <span class="result-label">Total Pixels:</span>
452
+ <span class="result-value">${imgInfo.total_pixels.toLocaleString()}</span>
453
+ </div>
454
+ <div class="result-item">
455
+ <span class="result-label">Size:</span>
456
+ <span class="result-value">${imgInfo.size_mb} MB</span>
457
+ </div>
458
+ <div class="result-item">
459
+ <span class="result-label">Data Type:</span>
460
+ <span class="result-value">${imgInfo.dtype}</span>
461
+ </div>
462
+ <div class="result-item">
463
+ <span class="result-label">Shape:</span>
464
+ <span class="result-value">[${imgInfo.shape.join(', ')}]</span>
465
+ </div>
466
+ <div class="result-item">
467
+ <span class="result-label">Processor Version:</span>
468
+ <span class="result-value">${result.processor_version}</span>
469
+ </div>
470
+ <div class="result-item">
471
+ <span class="result-label">Request ID:</span>
472
+ <span class="result-value">${result.request_id}</span>
473
+ </div>
474
+ `;
475
+
476
+ resultsContainer.style.display = 'block';
477
+ }
478
+
479
+ // Check system status
480
+ checkStatusBtn.addEventListener('click', async () => {
481
+ const apiUrl = apiUrlInput.value;
482
+
483
+ try {
484
+ showStatus('Checking system status...', 'processing');
485
+ const response = await fetch(`${apiUrl}/cerviguard_status`);
486
+ const data = await response.json();
487
+ const status = data.result;
488
+
489
+ showStatus(`✓ System Online | Service: ${status.service} | Version: ${status.version}`, 'success');
490
+ showStatus(`Total Requests: ${status.total_requests} | Pending: ${status.pending_requests} | Uptime: ${Math.round(status.uptime_seconds)}s`, 'info');
491
+
492
+ } catch (error) {
493
+ showStatus(`✗ Cannot connect to API: ${error.message}`, 'error');
494
+ }
495
+ });
496
+
497
+ // Show status message
498
+ function showStatus(message, type) {
499
+ const statusDiv = document.createElement('div');
500
+ statusDiv.className = `status ${type}`;
501
+ statusDiv.textContent = message;
502
+ statusContainer.appendChild(statusDiv);
503
+
504
+ // Auto-remove old messages
505
+ if (statusContainer.children.length > 5) {
506
+ statusContainer.removeChild(statusContainer.firstChild);
507
+ }
508
+ }
509
+
510
+ // Initial status check
511
+ window.addEventListener('load', () => {
512
+ setTimeout(() => checkStatusBtn.click(), 500);
513
+ });
514
+ </script>
515
+ </body>
516
+ </html>