synapse-sdk 1.0.0a13__py3-none-any.whl → 2025.11.7__py3-none-any.whl

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.

Potentially problematic release.


This version of synapse-sdk might be problematic. Click here for more details.

Files changed (339) hide show
  1. synapse_sdk/__init__.py +24 -0
  2. synapse_sdk/cli/__init__.py +310 -5
  3. synapse_sdk/cli/alias/__init__.py +22 -0
  4. synapse_sdk/cli/alias/create.py +36 -0
  5. synapse_sdk/cli/alias/dataclass.py +31 -0
  6. synapse_sdk/cli/alias/default.py +16 -0
  7. synapse_sdk/cli/alias/delete.py +15 -0
  8. synapse_sdk/cli/alias/list.py +19 -0
  9. synapse_sdk/cli/alias/read.py +15 -0
  10. synapse_sdk/cli/alias/update.py +17 -0
  11. synapse_sdk/cli/alias/utils.py +61 -0
  12. synapse_sdk/cli/code_server.py +687 -0
  13. synapse_sdk/cli/config.py +440 -0
  14. synapse_sdk/cli/devtools.py +90 -0
  15. synapse_sdk/cli/plugin/__init__.py +33 -0
  16. synapse_sdk/cli/{create_plugin.py → plugin/create.py} +2 -2
  17. synapse_sdk/cli/plugin/publish.py +45 -0
  18. synapse_sdk/{plugins/cli → cli/plugin}/run.py +12 -5
  19. synapse_sdk/clients/agent/__init__.py +9 -3
  20. synapse_sdk/clients/agent/container.py +133 -0
  21. synapse_sdk/clients/agent/core.py +19 -0
  22. synapse_sdk/clients/agent/ray.py +298 -9
  23. synapse_sdk/clients/backend/__init__.py +41 -12
  24. synapse_sdk/clients/backend/annotation.py +13 -5
  25. synapse_sdk/clients/backend/core.py +59 -0
  26. synapse_sdk/clients/backend/data_collection.py +186 -0
  27. synapse_sdk/clients/backend/hitl.py +17 -0
  28. synapse_sdk/clients/backend/integration.py +19 -4
  29. synapse_sdk/clients/backend/ml.py +10 -7
  30. synapse_sdk/clients/backend/models.py +78 -0
  31. synapse_sdk/clients/base.py +381 -34
  32. synapse_sdk/clients/ray/serve.py +2 -0
  33. synapse_sdk/clients/validators/collections.py +31 -0
  34. synapse_sdk/devtools/config.py +94 -0
  35. synapse_sdk/devtools/docs/.gitignore +20 -0
  36. synapse_sdk/devtools/docs/README.md +41 -0
  37. synapse_sdk/devtools/docs/blog/2019-05-28-first-blog-post.md +12 -0
  38. synapse_sdk/devtools/docs/blog/2019-05-29-long-blog-post.md +44 -0
  39. synapse_sdk/devtools/docs/blog/2021-08-01-mdx-blog-post.mdx +24 -0
  40. synapse_sdk/devtools/docs/blog/2021-08-26-welcome/docusaurus-plushie-banner.jpeg +0 -0
  41. synapse_sdk/devtools/docs/blog/2021-08-26-welcome/index.md +29 -0
  42. synapse_sdk/devtools/docs/blog/authors.yml +25 -0
  43. synapse_sdk/devtools/docs/blog/tags.yml +19 -0
  44. synapse_sdk/devtools/docs/docs/api/clients/agent.md +43 -0
  45. synapse_sdk/devtools/docs/docs/api/clients/annotation-mixin.md +378 -0
  46. synapse_sdk/devtools/docs/docs/api/clients/backend.md +420 -0
  47. synapse_sdk/devtools/docs/docs/api/clients/base.md +257 -0
  48. synapse_sdk/devtools/docs/docs/api/clients/core-mixin.md +477 -0
  49. synapse_sdk/devtools/docs/docs/api/clients/data-collection-mixin.md +422 -0
  50. synapse_sdk/devtools/docs/docs/api/clients/hitl-mixin.md +554 -0
  51. synapse_sdk/devtools/docs/docs/api/clients/index.md +391 -0
  52. synapse_sdk/devtools/docs/docs/api/clients/integration-mixin.md +571 -0
  53. synapse_sdk/devtools/docs/docs/api/clients/ml-mixin.md +578 -0
  54. synapse_sdk/devtools/docs/docs/api/clients/ray.md +342 -0
  55. synapse_sdk/devtools/docs/docs/api/index.md +52 -0
  56. synapse_sdk/devtools/docs/docs/api/plugins/categories.md +43 -0
  57. synapse_sdk/devtools/docs/docs/api/plugins/models.md +114 -0
  58. synapse_sdk/devtools/docs/docs/api/plugins/utils.md +328 -0
  59. synapse_sdk/devtools/docs/docs/categories.md +0 -0
  60. synapse_sdk/devtools/docs/docs/cli-usage.md +280 -0
  61. synapse_sdk/devtools/docs/docs/concepts/index.md +38 -0
  62. synapse_sdk/devtools/docs/docs/configuration.md +83 -0
  63. synapse_sdk/devtools/docs/docs/contributing.md +306 -0
  64. synapse_sdk/devtools/docs/docs/examples/index.md +29 -0
  65. synapse_sdk/devtools/docs/docs/faq.md +179 -0
  66. synapse_sdk/devtools/docs/docs/features/converters/index.md +455 -0
  67. synapse_sdk/devtools/docs/docs/features/index.md +24 -0
  68. synapse_sdk/devtools/docs/docs/features/utils/file.md +415 -0
  69. synapse_sdk/devtools/docs/docs/features/utils/network.md +378 -0
  70. synapse_sdk/devtools/docs/docs/features/utils/storage.md +57 -0
  71. synapse_sdk/devtools/docs/docs/features/utils/types.md +51 -0
  72. synapse_sdk/devtools/docs/docs/installation.md +94 -0
  73. synapse_sdk/devtools/docs/docs/introduction.md +47 -0
  74. synapse_sdk/devtools/docs/docs/plugins/categories/neural-net-plugins/train-action-overview.md +814 -0
  75. synapse_sdk/devtools/docs/docs/plugins/categories/pre-annotation-plugins/pre-annotation-plugin-overview.md +198 -0
  76. synapse_sdk/devtools/docs/docs/plugins/categories/pre-annotation-plugins/to-task-action-development.md +1645 -0
  77. synapse_sdk/devtools/docs/docs/plugins/categories/pre-annotation-plugins/to-task-overview.md +717 -0
  78. synapse_sdk/devtools/docs/docs/plugins/categories/pre-annotation-plugins/to-task-template-development.md +1380 -0
  79. synapse_sdk/devtools/docs/docs/plugins/categories/upload-plugins/upload-plugin-action.md +948 -0
  80. synapse_sdk/devtools/docs/docs/plugins/categories/upload-plugins/upload-plugin-overview.md +544 -0
  81. synapse_sdk/devtools/docs/docs/plugins/categories/upload-plugins/upload-plugin-template.md +766 -0
  82. synapse_sdk/devtools/docs/docs/plugins/export-plugins.md +1092 -0
  83. synapse_sdk/devtools/docs/docs/plugins/plugins.md +852 -0
  84. synapse_sdk/devtools/docs/docs/quickstart.md +78 -0
  85. synapse_sdk/devtools/docs/docs/troubleshooting.md +519 -0
  86. synapse_sdk/devtools/docs/docs/tutorial-basics/_category_.json +8 -0
  87. synapse_sdk/devtools/docs/docs/tutorial-basics/congratulations.md +23 -0
  88. synapse_sdk/devtools/docs/docs/tutorial-basics/create-a-blog-post.md +34 -0
  89. synapse_sdk/devtools/docs/docs/tutorial-basics/create-a-document.md +57 -0
  90. synapse_sdk/devtools/docs/docs/tutorial-basics/create-a-page.md +43 -0
  91. synapse_sdk/devtools/docs/docs/tutorial-basics/deploy-your-site.md +31 -0
  92. synapse_sdk/devtools/docs/docs/tutorial-basics/markdown-features.mdx +152 -0
  93. synapse_sdk/devtools/docs/docs/tutorial-extras/_category_.json +7 -0
  94. synapse_sdk/devtools/docs/docs/tutorial-extras/img/docsVersionDropdown.png +0 -0
  95. synapse_sdk/devtools/docs/docs/tutorial-extras/img/localeDropdown.png +0 -0
  96. synapse_sdk/devtools/docs/docs/tutorial-extras/manage-docs-versions.md +55 -0
  97. synapse_sdk/devtools/docs/docs/tutorial-extras/translate-your-site.md +88 -0
  98. synapse_sdk/devtools/docs/docusaurus.config.ts +148 -0
  99. synapse_sdk/devtools/docs/i18n/ko/code.json +325 -0
  100. synapse_sdk/devtools/docs/i18n/ko/docusaurus-plugin-content-docs/current/api/clients/agent.md +43 -0
  101. synapse_sdk/devtools/docs/i18n/ko/docusaurus-plugin-content-docs/current/api/clients/annotation-mixin.md +289 -0
  102. synapse_sdk/devtools/docs/i18n/ko/docusaurus-plugin-content-docs/current/api/clients/backend.md +420 -0
  103. synapse_sdk/devtools/docs/i18n/ko/docusaurus-plugin-content-docs/current/api/clients/base.md +257 -0
  104. synapse_sdk/devtools/docs/i18n/ko/docusaurus-plugin-content-docs/current/api/clients/core-mixin.md +417 -0
  105. synapse_sdk/devtools/docs/i18n/ko/docusaurus-plugin-content-docs/current/api/clients/data-collection-mixin.md +356 -0
  106. synapse_sdk/devtools/docs/i18n/ko/docusaurus-plugin-content-docs/current/api/clients/hitl-mixin.md +192 -0
  107. synapse_sdk/devtools/docs/i18n/ko/docusaurus-plugin-content-docs/current/api/clients/index.md +391 -0
  108. synapse_sdk/devtools/docs/i18n/ko/docusaurus-plugin-content-docs/current/api/clients/integration-mixin.md +479 -0
  109. synapse_sdk/devtools/docs/i18n/ko/docusaurus-plugin-content-docs/current/api/clients/ml-mixin.md +284 -0
  110. synapse_sdk/devtools/docs/i18n/ko/docusaurus-plugin-content-docs/current/api/clients/ray.md +342 -0
  111. synapse_sdk/devtools/docs/i18n/ko/docusaurus-plugin-content-docs/current/api/index.md +52 -0
  112. synapse_sdk/devtools/docs/i18n/ko/docusaurus-plugin-content-docs/current/api/plugins/models.md +114 -0
  113. synapse_sdk/devtools/docs/i18n/ko/docusaurus-plugin-content-docs/current/categories.md +0 -0
  114. synapse_sdk/devtools/docs/i18n/ko/docusaurus-plugin-content-docs/current/cli-usage.md +280 -0
  115. synapse_sdk/devtools/docs/i18n/ko/docusaurus-plugin-content-docs/current/concepts/index.md +38 -0
  116. synapse_sdk/devtools/docs/i18n/ko/docusaurus-plugin-content-docs/current/configuration.md +83 -0
  117. synapse_sdk/devtools/docs/i18n/ko/docusaurus-plugin-content-docs/current/contributing.md +306 -0
  118. synapse_sdk/devtools/docs/i18n/ko/docusaurus-plugin-content-docs/current/examples/index.md +29 -0
  119. synapse_sdk/devtools/docs/i18n/ko/docusaurus-plugin-content-docs/current/faq.md +179 -0
  120. synapse_sdk/devtools/docs/i18n/ko/docusaurus-plugin-content-docs/current/features/converters/index.md +30 -0
  121. synapse_sdk/devtools/docs/i18n/ko/docusaurus-plugin-content-docs/current/features/index.md +24 -0
  122. synapse_sdk/devtools/docs/i18n/ko/docusaurus-plugin-content-docs/current/features/utils/file.md +415 -0
  123. synapse_sdk/devtools/docs/i18n/ko/docusaurus-plugin-content-docs/current/features/utils/network.md +378 -0
  124. synapse_sdk/devtools/docs/i18n/ko/docusaurus-plugin-content-docs/current/features/utils/storage.md +60 -0
  125. synapse_sdk/devtools/docs/i18n/ko/docusaurus-plugin-content-docs/current/features/utils/types.md +51 -0
  126. synapse_sdk/devtools/docs/i18n/ko/docusaurus-plugin-content-docs/current/installation.md +94 -0
  127. synapse_sdk/devtools/docs/i18n/ko/docusaurus-plugin-content-docs/current/introduction.md +47 -0
  128. synapse_sdk/devtools/docs/i18n/ko/docusaurus-plugin-content-docs/current/plugins/categories/neural-net-plugins/train-action-overview.md +815 -0
  129. synapse_sdk/devtools/docs/i18n/ko/docusaurus-plugin-content-docs/current/plugins/categories/pre-annotation-plugins/pre-annotation-plugin-overview.md +198 -0
  130. synapse_sdk/devtools/docs/i18n/ko/docusaurus-plugin-content-docs/current/plugins/categories/pre-annotation-plugins/to-task-action-development.md +1645 -0
  131. synapse_sdk/devtools/docs/i18n/ko/docusaurus-plugin-content-docs/current/plugins/categories/pre-annotation-plugins/to-task-overview.md +717 -0
  132. synapse_sdk/devtools/docs/i18n/ko/docusaurus-plugin-content-docs/current/plugins/categories/pre-annotation-plugins/to-task-template-development.md +1380 -0
  133. synapse_sdk/devtools/docs/i18n/ko/docusaurus-plugin-content-docs/current/plugins/categories/upload-plugins/upload-plugin-action.md +948 -0
  134. synapse_sdk/devtools/docs/i18n/ko/docusaurus-plugin-content-docs/current/plugins/categories/upload-plugins/upload-plugin-overview.md +544 -0
  135. synapse_sdk/devtools/docs/i18n/ko/docusaurus-plugin-content-docs/current/plugins/categories/upload-plugins/upload-plugin-template.md +766 -0
  136. synapse_sdk/devtools/docs/i18n/ko/docusaurus-plugin-content-docs/current/plugins/export-plugins.md +1092 -0
  137. synapse_sdk/devtools/docs/i18n/ko/docusaurus-plugin-content-docs/current/plugins/plugins.md +117 -0
  138. synapse_sdk/devtools/docs/i18n/ko/docusaurus-plugin-content-docs/current/quickstart.md +78 -0
  139. synapse_sdk/devtools/docs/i18n/ko/docusaurus-plugin-content-docs/current/troubleshooting.md +519 -0
  140. synapse_sdk/devtools/docs/i18n/ko/docusaurus-plugin-content-docs/current.json +34 -0
  141. synapse_sdk/devtools/docs/i18n/ko/docusaurus-theme-classic/footer.json +42 -0
  142. synapse_sdk/devtools/docs/i18n/ko/docusaurus-theme-classic/navbar.json +18 -0
  143. synapse_sdk/devtools/docs/package-lock.json +18784 -0
  144. synapse_sdk/devtools/docs/package.json +48 -0
  145. synapse_sdk/devtools/docs/sidebars.ts +122 -0
  146. synapse_sdk/devtools/docs/src/components/HomepageFeatures/index.tsx +71 -0
  147. synapse_sdk/devtools/docs/src/components/HomepageFeatures/styles.module.css +11 -0
  148. synapse_sdk/devtools/docs/src/css/custom.css +30 -0
  149. synapse_sdk/devtools/docs/src/pages/index.module.css +23 -0
  150. synapse_sdk/devtools/docs/src/pages/index.tsx +21 -0
  151. synapse_sdk/devtools/docs/src/pages/markdown-page.md +7 -0
  152. synapse_sdk/devtools/docs/static/.nojekyll +0 -0
  153. synapse_sdk/devtools/docs/static/img/docusaurus-social-card.jpg +0 -0
  154. synapse_sdk/devtools/docs/static/img/docusaurus.png +0 -0
  155. synapse_sdk/devtools/docs/static/img/favicon.ico +0 -0
  156. synapse_sdk/devtools/docs/static/img/logo.png +0 -0
  157. synapse_sdk/devtools/docs/static/img/undraw_docusaurus_mountain.svg +171 -0
  158. synapse_sdk/devtools/docs/static/img/undraw_docusaurus_react.svg +170 -0
  159. synapse_sdk/devtools/docs/static/img/undraw_docusaurus_tree.svg +40 -0
  160. synapse_sdk/devtools/docs/tsconfig.json +8 -0
  161. synapse_sdk/devtools/server.py +41 -0
  162. synapse_sdk/devtools/streamlit_app/__init__.py +5 -0
  163. synapse_sdk/devtools/streamlit_app/app.py +128 -0
  164. synapse_sdk/devtools/streamlit_app/services/__init__.py +11 -0
  165. synapse_sdk/devtools/streamlit_app/services/job_service.py +233 -0
  166. synapse_sdk/devtools/streamlit_app/services/plugin_service.py +236 -0
  167. synapse_sdk/devtools/streamlit_app/services/serve_service.py +95 -0
  168. synapse_sdk/devtools/streamlit_app/ui/__init__.py +15 -0
  169. synapse_sdk/devtools/streamlit_app/ui/config_tab.py +76 -0
  170. synapse_sdk/devtools/streamlit_app/ui/deployment_tab.py +66 -0
  171. synapse_sdk/devtools/streamlit_app/ui/http_tab.py +125 -0
  172. synapse_sdk/devtools/streamlit_app/ui/jobs_tab.py +573 -0
  173. synapse_sdk/devtools/streamlit_app/ui/serve_tab.py +346 -0
  174. synapse_sdk/devtools/streamlit_app/ui/status_bar.py +118 -0
  175. synapse_sdk/devtools/streamlit_app/utils/__init__.py +40 -0
  176. synapse_sdk/devtools/streamlit_app/utils/json_viewer.py +197 -0
  177. synapse_sdk/devtools/streamlit_app/utils/log_formatter.py +38 -0
  178. synapse_sdk/devtools/streamlit_app/utils/styles.py +241 -0
  179. synapse_sdk/devtools/streamlit_app/utils/ui_components.py +289 -0
  180. synapse_sdk/devtools/streamlit_app.py +10 -0
  181. synapse_sdk/loggers.py +74 -9
  182. synapse_sdk/plugins/README.md +1340 -0
  183. synapse_sdk/plugins/__init__.py +0 -13
  184. synapse_sdk/plugins/categories/base.py +145 -30
  185. synapse_sdk/plugins/categories/data_validation/actions/validation.py +72 -0
  186. synapse_sdk/plugins/categories/data_validation/templates/plugin/validation.py +33 -5
  187. synapse_sdk/plugins/categories/export/actions/__init__.py +3 -0
  188. synapse_sdk/plugins/categories/export/actions/export/__init__.py +28 -0
  189. synapse_sdk/plugins/categories/export/actions/export/action.py +165 -0
  190. synapse_sdk/plugins/categories/export/actions/export/enums.py +113 -0
  191. synapse_sdk/plugins/categories/export/actions/export/exceptions.py +53 -0
  192. synapse_sdk/plugins/categories/export/actions/export/models.py +74 -0
  193. synapse_sdk/plugins/categories/export/actions/export/run.py +195 -0
  194. synapse_sdk/plugins/categories/export/actions/export/utils.py +187 -0
  195. synapse_sdk/plugins/categories/export/templates/config.yaml +21 -0
  196. synapse_sdk/plugins/categories/export/templates/plugin/__init__.py +390 -0
  197. synapse_sdk/plugins/categories/export/templates/plugin/export.py +160 -0
  198. synapse_sdk/plugins/categories/neural_net/actions/deployment.py +29 -14
  199. synapse_sdk/plugins/categories/neural_net/actions/inference.py +13 -1
  200. synapse_sdk/plugins/categories/neural_net/actions/train.py +1084 -38
  201. synapse_sdk/plugins/categories/neural_net/actions/tune.py +534 -0
  202. synapse_sdk/plugins/categories/neural_net/base/__init__.py +0 -0
  203. synapse_sdk/plugins/categories/neural_net/base/inference.py +37 -0
  204. synapse_sdk/plugins/categories/neural_net/templates/config.yaml +30 -5
  205. synapse_sdk/plugins/categories/neural_net/templates/plugin/inference.py +26 -10
  206. synapse_sdk/plugins/categories/pre_annotation/actions/__init__.py +4 -0
  207. synapse_sdk/plugins/categories/pre_annotation/actions/pre_annotation/__init__.py +3 -0
  208. synapse_sdk/plugins/categories/{export/actions/export.py → pre_annotation/actions/pre_annotation/action.py} +4 -4
  209. synapse_sdk/plugins/categories/pre_annotation/actions/to_task/__init__.py +28 -0
  210. synapse_sdk/plugins/categories/pre_annotation/actions/to_task/action.py +145 -0
  211. synapse_sdk/plugins/categories/pre_annotation/actions/to_task/enums.py +269 -0
  212. synapse_sdk/plugins/categories/pre_annotation/actions/to_task/exceptions.py +14 -0
  213. synapse_sdk/plugins/categories/pre_annotation/actions/to_task/factory.py +76 -0
  214. synapse_sdk/plugins/categories/pre_annotation/actions/to_task/models.py +97 -0
  215. synapse_sdk/plugins/categories/pre_annotation/actions/to_task/orchestrator.py +250 -0
  216. synapse_sdk/plugins/categories/pre_annotation/actions/to_task/run.py +64 -0
  217. synapse_sdk/plugins/categories/pre_annotation/actions/to_task/strategies/__init__.py +17 -0
  218. synapse_sdk/plugins/categories/pre_annotation/actions/to_task/strategies/annotation.py +287 -0
  219. synapse_sdk/plugins/categories/pre_annotation/actions/to_task/strategies/base.py +170 -0
  220. synapse_sdk/plugins/categories/pre_annotation/actions/to_task/strategies/extraction.py +83 -0
  221. synapse_sdk/plugins/categories/pre_annotation/actions/to_task/strategies/metrics.py +87 -0
  222. synapse_sdk/plugins/categories/pre_annotation/actions/to_task/strategies/preprocessor.py +127 -0
  223. synapse_sdk/plugins/categories/pre_annotation/actions/to_task/strategies/validation.py +143 -0
  224. synapse_sdk/plugins/categories/pre_annotation/actions/to_task.py +966 -0
  225. synapse_sdk/plugins/categories/pre_annotation/templates/config.yaml +19 -0
  226. synapse_sdk/plugins/categories/pre_annotation/templates/plugin/to_task.py +40 -0
  227. synapse_sdk/plugins/categories/smart_tool/templates/config.yaml +5 -2
  228. synapse_sdk/plugins/categories/upload/__init__.py +0 -0
  229. synapse_sdk/plugins/categories/upload/actions/__init__.py +0 -0
  230. synapse_sdk/plugins/categories/upload/actions/upload/__init__.py +19 -0
  231. synapse_sdk/plugins/categories/upload/actions/upload/action.py +232 -0
  232. synapse_sdk/plugins/categories/upload/actions/upload/context.py +185 -0
  233. synapse_sdk/plugins/categories/upload/actions/upload/enums.py +471 -0
  234. synapse_sdk/plugins/categories/upload/actions/upload/exceptions.py +36 -0
  235. synapse_sdk/plugins/categories/upload/actions/upload/factory.py +138 -0
  236. synapse_sdk/plugins/categories/upload/actions/upload/models.py +203 -0
  237. synapse_sdk/plugins/categories/upload/actions/upload/orchestrator.py +183 -0
  238. synapse_sdk/plugins/categories/upload/actions/upload/registry.py +113 -0
  239. synapse_sdk/plugins/categories/upload/actions/upload/run.py +179 -0
  240. synapse_sdk/plugins/categories/upload/actions/upload/steps/__init__.py +1 -0
  241. synapse_sdk/plugins/categories/upload/actions/upload/steps/base.py +107 -0
  242. synapse_sdk/plugins/categories/upload/actions/upload/steps/cleanup.py +62 -0
  243. synapse_sdk/plugins/categories/upload/actions/upload/steps/collection.py +63 -0
  244. synapse_sdk/plugins/categories/upload/actions/upload/steps/generate.py +84 -0
  245. synapse_sdk/plugins/categories/upload/actions/upload/steps/initialize.py +82 -0
  246. synapse_sdk/plugins/categories/upload/actions/upload/steps/metadata.py +235 -0
  247. synapse_sdk/plugins/categories/upload/actions/upload/steps/organize.py +203 -0
  248. synapse_sdk/plugins/categories/upload/actions/upload/steps/upload.py +97 -0
  249. synapse_sdk/plugins/categories/upload/actions/upload/steps/validate.py +71 -0
  250. synapse_sdk/plugins/categories/upload/actions/upload/strategies/__init__.py +1 -0
  251. synapse_sdk/plugins/categories/upload/actions/upload/strategies/base.py +82 -0
  252. synapse_sdk/plugins/categories/upload/actions/upload/strategies/data_unit/__init__.py +1 -0
  253. synapse_sdk/plugins/categories/upload/actions/upload/strategies/data_unit/batch.py +39 -0
  254. synapse_sdk/plugins/categories/upload/actions/upload/strategies/data_unit/single.py +29 -0
  255. synapse_sdk/plugins/categories/upload/actions/upload/strategies/file_discovery/__init__.py +1 -0
  256. synapse_sdk/plugins/categories/upload/actions/upload/strategies/file_discovery/flat.py +258 -0
  257. synapse_sdk/plugins/categories/upload/actions/upload/strategies/file_discovery/recursive.py +281 -0
  258. synapse_sdk/plugins/categories/upload/actions/upload/strategies/metadata/__init__.py +1 -0
  259. synapse_sdk/plugins/categories/upload/actions/upload/strategies/metadata/excel.py +174 -0
  260. synapse_sdk/plugins/categories/upload/actions/upload/strategies/metadata/none.py +16 -0
  261. synapse_sdk/plugins/categories/upload/actions/upload/strategies/upload/__init__.py +1 -0
  262. synapse_sdk/plugins/categories/upload/actions/upload/strategies/upload/sync.py +84 -0
  263. synapse_sdk/plugins/categories/upload/actions/upload/strategies/validation/__init__.py +1 -0
  264. synapse_sdk/plugins/categories/upload/actions/upload/strategies/validation/default.py +60 -0
  265. synapse_sdk/plugins/categories/upload/actions/upload/utils.py +250 -0
  266. synapse_sdk/plugins/categories/upload/templates/README.md +470 -0
  267. synapse_sdk/plugins/categories/upload/templates/config.yaml +33 -0
  268. synapse_sdk/plugins/categories/upload/templates/plugin/__init__.py +294 -0
  269. synapse_sdk/plugins/categories/upload/templates/plugin/upload.py +102 -0
  270. synapse_sdk/plugins/enums.py +3 -1
  271. synapse_sdk/plugins/models.py +140 -16
  272. synapse_sdk/plugins/templates/plugin-config-schema.json +406 -0
  273. synapse_sdk/plugins/templates/schema.json +491 -0
  274. synapse_sdk/plugins/templates/synapse-{{cookiecutter.plugin_code}}-plugin/config.yaml +1 -0
  275. synapse_sdk/plugins/templates/synapse-{{cookiecutter.plugin_code}}-plugin/requirements.txt +1 -1
  276. synapse_sdk/plugins/utils/__init__.py +46 -0
  277. synapse_sdk/plugins/utils/actions.py +119 -0
  278. synapse_sdk/plugins/utils/config.py +203 -0
  279. synapse_sdk/plugins/utils/legacy.py +95 -0
  280. synapse_sdk/plugins/utils/ray_gcs.py +66 -0
  281. synapse_sdk/plugins/utils/registry.py +58 -0
  282. synapse_sdk/shared/__init__.py +25 -0
  283. synapse_sdk/shared/enums.py +93 -0
  284. synapse_sdk/types.py +19 -0
  285. synapse_sdk/utils/converters/__init__.py +240 -0
  286. synapse_sdk/utils/converters/coco/__init__.py +0 -0
  287. synapse_sdk/utils/converters/coco/from_dm.py +322 -0
  288. synapse_sdk/utils/converters/coco/to_dm.py +215 -0
  289. synapse_sdk/utils/converters/dm/__init__.py +56 -0
  290. synapse_sdk/utils/converters/dm/from_v1.py +627 -0
  291. synapse_sdk/utils/converters/dm/to_v1.py +367 -0
  292. synapse_sdk/utils/converters/pascal/__init__.py +0 -0
  293. synapse_sdk/utils/converters/pascal/from_dm.py +244 -0
  294. synapse_sdk/utils/converters/pascal/to_dm.py +214 -0
  295. synapse_sdk/utils/converters/yolo/__init__.py +0 -0
  296. synapse_sdk/utils/converters/yolo/from_dm.py +384 -0
  297. synapse_sdk/utils/converters/yolo/to_dm.py +267 -0
  298. synapse_sdk/utils/dataset.py +46 -0
  299. synapse_sdk/utils/encryption.py +158 -0
  300. synapse_sdk/utils/file/__init__.py +39 -0
  301. synapse_sdk/utils/file/archive.py +32 -0
  302. synapse_sdk/utils/file/checksum.py +56 -0
  303. synapse_sdk/utils/file/chunking.py +31 -0
  304. synapse_sdk/utils/file/download.py +385 -0
  305. synapse_sdk/utils/file/encoding.py +40 -0
  306. synapse_sdk/utils/file/io.py +22 -0
  307. synapse_sdk/utils/file/video/__init__.py +29 -0
  308. synapse_sdk/utils/file/video/transcode.py +307 -0
  309. synapse_sdk/utils/file.py.backup +301 -0
  310. synapse_sdk/utils/http.py +138 -0
  311. synapse_sdk/utils/network.py +309 -0
  312. synapse_sdk/utils/storage/__init__.py +72 -0
  313. synapse_sdk/utils/storage/providers/__init__.py +183 -0
  314. synapse_sdk/utils/storage/providers/file_system.py +134 -0
  315. synapse_sdk/utils/storage/providers/gcp.py +13 -0
  316. synapse_sdk/utils/storage/providers/http.py +190 -0
  317. synapse_sdk/utils/storage/providers/s3.py +91 -0
  318. synapse_sdk/utils/storage/providers/sftp.py +47 -0
  319. synapse_sdk/utils/storage/registry.py +17 -0
  320. synapse_sdk-2025.11.7.dist-info/METADATA +122 -0
  321. synapse_sdk-2025.11.7.dist-info/RECORD +386 -0
  322. {synapse_sdk-1.0.0a13.dist-info → synapse_sdk-2025.11.7.dist-info}/WHEEL +1 -1
  323. synapse_sdk/clients/backend/dataset.py +0 -51
  324. synapse_sdk/plugins/categories/import/actions/import.py +0 -10
  325. synapse_sdk/plugins/cli/__init__.py +0 -21
  326. synapse_sdk/plugins/cli/publish.py +0 -37
  327. synapse_sdk/plugins/templates/synapse-{{cookiecutter.plugin_code}}-plugin/.env +0 -24
  328. synapse_sdk/plugins/templates/synapse-{{cookiecutter.plugin_code}}-plugin/.env.dist +0 -24
  329. synapse_sdk/plugins/templates/synapse-{{cookiecutter.plugin_code}}-plugin/main.py +0 -4
  330. synapse_sdk/plugins/utils.py +0 -50
  331. synapse_sdk/utils/file.py +0 -87
  332. synapse_sdk/utils/storage.py +0 -91
  333. synapse_sdk-1.0.0a13.dist-info/METADATA +0 -43
  334. synapse_sdk-1.0.0a13.dist-info/RECORD +0 -111
  335. /synapse_sdk/{plugins/categories/import → clients/validators}/__init__.py +0 -0
  336. /synapse_sdk/{plugins/categories/import/actions → devtools}/__init__.py +0 -0
  337. {synapse_sdk-1.0.0a13.dist-info → synapse_sdk-2025.11.7.dist-info}/entry_points.txt +0 -0
  338. {synapse_sdk-1.0.0a13.dist-info → synapse_sdk-2025.11.7.dist-info/licenses}/LICENSE +0 -0
  339. {synapse_sdk-1.0.0a13.dist-info → synapse_sdk-2025.11.7.dist-info}/top_level.txt +0 -0
@@ -0,0 +1,573 @@
1
+ """Jobs tab UI component."""
2
+
3
+ import time
4
+ import traceback
5
+ from typing import Dict, Optional
6
+
7
+ import streamlit as st
8
+
9
+ from synapse_sdk.clients.exceptions import ClientError
10
+
11
+ from ..services.job_service import JobService
12
+ from ..utils.json_viewer import render_json_as_table, render_json_compact, render_metrics_grid
13
+ from ..utils.log_formatter import format_log_line
14
+ from ..utils.styles import get_status_badge_html
15
+ from ..utils.ui_components import (
16
+ render_action_button,
17
+ render_empty_state,
18
+ render_section_header,
19
+ )
20
+
21
+
22
+ class JobsTab:
23
+ """UI component for the Jobs tab."""
24
+
25
+ def __init__(self, job_service: JobService, agent_id: Optional[int] = None, agent_info: Optional[Dict] = None):
26
+ self.job_service = job_service
27
+ self.agent_id = agent_id
28
+ self.agent_info = agent_info or {}
29
+
30
+ def render(self):
31
+ """Render the Jobs tab."""
32
+ if not self.job_service.backend_client:
33
+ st.error('Backend client not configured. Please check your backend configuration.')
34
+ return
35
+
36
+ # Check if we should show job details
37
+ if 'selected_job' in st.session_state:
38
+ self.render_job_details(st.session_state['selected_job'])
39
+ return
40
+
41
+ # Controls row
42
+ col1, col2, col3 = st.columns([1, 1, 2])
43
+ with col1:
44
+ if render_action_button('Refresh', key='refresh_jobs', icon='🔄', type='secondary'):
45
+ st.rerun()
46
+
47
+ with col2:
48
+ auto_refresh = st.checkbox('Auto-refresh', value=False, key='jobs_auto_refresh')
49
+
50
+ with col3:
51
+ if auto_refresh:
52
+ refresh_interval = st.selectbox(
53
+ 'Refresh interval',
54
+ options=[2, 5, 10, 30],
55
+ index=1, # Default to 5 seconds
56
+ format_func=lambda x: f'{x}s',
57
+ key='jobs_refresh_interval',
58
+ )
59
+
60
+ # Get page size from session state or use default
61
+ page_size = st.session_state.get('page_size_value', 20)
62
+
63
+ # Initialize pagination state
64
+ if 'current_page' not in st.session_state:
65
+ st.session_state.current_page = 0
66
+
67
+ try:
68
+ valid_jobs = self.job_service.list_jobs(self.agent_id, self.agent_info)
69
+
70
+ # Pagination logic
71
+ total_jobs = len(valid_jobs)
72
+ total_pages = (total_jobs + page_size - 1) // page_size if total_jobs > 0 else 1
73
+
74
+ # Ensure current page is valid
75
+ if st.session_state.current_page >= total_pages:
76
+ st.session_state.current_page = max(0, total_pages - 1)
77
+
78
+ start_idx = st.session_state.current_page * page_size
79
+ end_idx = min(start_idx + page_size, total_jobs)
80
+ page_jobs = valid_jobs[start_idx:end_idx]
81
+
82
+ # Display job count info
83
+ if total_jobs > 0:
84
+ st.success(f'Showing {start_idx + 1}-{end_idx} of {total_jobs} jobs')
85
+ else:
86
+ render_empty_state(
87
+ 'No jobs found', icon='📋', action_label='Refresh', action_callback=lambda: st.rerun()
88
+ )
89
+ return
90
+
91
+ # Display jobs in table format
92
+ if page_jobs:
93
+ self._render_jobs_table(page_jobs)
94
+
95
+ # Pagination controls at the bottom
96
+ if total_pages > 1 or total_jobs > 10:
97
+ self._render_pagination_controls(total_pages, page_size)
98
+
99
+ except ClientError as e:
100
+ st.error(f'Failed to fetch jobs: {e.reason}')
101
+ except Exception as e:
102
+ st.error(f'Unexpected error: {e}')
103
+ st.code(traceback.format_exc())
104
+
105
+ # Auto-refresh implementation
106
+ if auto_refresh:
107
+ refresh_interval = st.session_state.get('jobs_refresh_interval', 5)
108
+ placeholder = st.empty()
109
+ with placeholder.container():
110
+ st.info(f'Refreshing in {refresh_interval} seconds...')
111
+ time.sleep(refresh_interval)
112
+ placeholder.empty()
113
+ st.rerun()
114
+
115
+ def _render_jobs_table(self, jobs):
116
+ """Render the jobs table."""
117
+ # Table header with balanced spacing
118
+ header_cols = st.columns([2, 1.2, 1.5, 1, 0.8, 1, 0.6, 1.2])
119
+ headers = ['Job', 'Plugin', 'User', 'Status', 'Progress', 'Duration', '', 'Created']
120
+
121
+ for i, header in enumerate(headers):
122
+ with header_cols[i]:
123
+ st.markdown(
124
+ f"<div style='color:#666; font-size:13px; font-weight:600; padding: 4px 0;'>{header}</div>",
125
+ unsafe_allow_html=True,
126
+ )
127
+
128
+ st.markdown("<hr style='margin: 8px 0; border: none; border-top: 1px solid #e0e0e0'>", unsafe_allow_html=True)
129
+
130
+ # Table rows with balanced spacing
131
+ for job in jobs:
132
+ cols = st.columns([2, 1.2, 1.5, 1, 0.8, 1, 0.6, 1.2])
133
+
134
+ # Job Name/ID
135
+ with cols[0]:
136
+ job_id = job.get('id', 'N/A')
137
+ # Try to get job name from various fields
138
+ job_name = (
139
+ job.get('name')
140
+ or job.get('display_name')
141
+ or job.get('action')
142
+ or (job.get('params', {}).get('name') if isinstance(job.get('params'), dict) else None)
143
+ or f'Job {str(job_id)[:8]}...'
144
+ )
145
+
146
+ # Display name with ID as subtitle
147
+ st.markdown(
148
+ f"<div style='font-size:13px; padding: 6px 0;'>"
149
+ f"<div style='font-weight: 500;'>{job_name}</div>"
150
+ f"<div style='font-size: 11px; color: #666; font-family: monospace;'>{str(job_id)[:8]}...</div>"
151
+ f'</div>',
152
+ unsafe_allow_html=True,
153
+ )
154
+
155
+ # Plugin Category
156
+ with cols[1]:
157
+ plugin_category = job.get('plugin_category', 'N/A')
158
+ st.markdown(
159
+ f"<div style='font-size:13px; padding: 6px 0;'>{plugin_category}</div>",
160
+ unsafe_allow_html=True,
161
+ )
162
+
163
+ # User
164
+ with cols[2]:
165
+ user = job.get('user', {})
166
+ user_name = user.get('name', user.get('email', 'N/A'))
167
+ display_name = user_name[:12] + '...' if len(str(user_name)) > 12 else str(user_name)
168
+ st.markdown(
169
+ f"<div style='font-size:13px; padding: 6px 0;'>{display_name}</div>", unsafe_allow_html=True
170
+ )
171
+
172
+ # Status with badge
173
+ with cols[3]:
174
+ status = job.get('status', 'Unknown')
175
+ st.markdown(get_status_badge_html(status), unsafe_allow_html=True)
176
+
177
+ # Progress
178
+ with cols[4]:
179
+ progress = job.get('progress', {})
180
+ overall = progress.get('overall', 0)
181
+ if overall is not None:
182
+ st.markdown(
183
+ f"<div style='font-size:13px; padding: 6px 0;'>{overall}%</div>", unsafe_allow_html=True
184
+ )
185
+ else:
186
+ st.markdown("<div style='font-size:13px; padding: 6px 0;'>-</div>", unsafe_allow_html=True)
187
+
188
+ # Duration
189
+ with cols[5]:
190
+ duration_text = self.job_service.format_duration(job.get('created'), job.get('completed'))
191
+ st.markdown(
192
+ f"<div style='font-size:13px; padding: 6px 0;'>{duration_text}</div>",
193
+ unsafe_allow_html=True,
194
+ )
195
+
196
+ # Actions
197
+ with cols[6]:
198
+ logs_key = f'logs_{job.get("id")}_{hash(str(job))}'
199
+
200
+ def select_job(job):
201
+ st.session_state['selected_job'] = job
202
+
203
+ # Compact view button
204
+ if render_action_button(
205
+ '', key=logs_key, icon='→', type='minimal', on_click=select_job, args=(job,), help='View details'
206
+ ):
207
+ pass
208
+
209
+ # Start Time
210
+ with cols[7]:
211
+ time_str = self.job_service.format_timestamp(job.get('created'))
212
+ st.markdown(
213
+ f"<div style='font-size:13px; padding: 6px 0;'>{time_str}</div>",
214
+ unsafe_allow_html=True,
215
+ )
216
+
217
+ st.markdown(
218
+ "<hr style='margin: 6px 0; border: none; border-top: 1px solid #f0f0f0'>",
219
+ unsafe_allow_html=True,
220
+ )
221
+
222
+ def _render_pagination_controls(self, total_pages, page_size):
223
+ """Render pagination controls."""
224
+ st.markdown('---')
225
+ col1, col2, col3, col4, col5, col6 = st.columns([1, 1, 1.5, 1, 1, 1.5])
226
+
227
+ with col1:
228
+ if render_action_button(
229
+ 'First', key='bottom_first', type='minimal', disabled=st.session_state.current_page == 0
230
+ ):
231
+ st.session_state.current_page = 0
232
+ st.rerun()
233
+
234
+ with col2:
235
+ if render_action_button(
236
+ 'Prev', key='bottom_prev', type='minimal', disabled=st.session_state.current_page == 0
237
+ ):
238
+ st.session_state.current_page -= 1
239
+ st.rerun()
240
+
241
+ with col3:
242
+ st.markdown(
243
+ f'<div style="text-align: center; padding: 8px; color: #495057; font-size: 14px;">'
244
+ f'Page {st.session_state.current_page + 1} of {total_pages}</div>',
245
+ unsafe_allow_html=True,
246
+ )
247
+
248
+ with col4:
249
+ if render_action_button(
250
+ 'Next', key='bottom_next', type='minimal', disabled=st.session_state.current_page >= total_pages - 1
251
+ ):
252
+ st.session_state.current_page += 1
253
+ st.rerun()
254
+
255
+ with col5:
256
+ if render_action_button(
257
+ 'Last', key='bottom_last', type='minimal', disabled=st.session_state.current_page >= total_pages - 1
258
+ ):
259
+ st.session_state.current_page = total_pages - 1
260
+ st.rerun()
261
+
262
+ with col6:
263
+ new_page_size = st.selectbox(
264
+ 'Items per page',
265
+ options=[10, 20, 50, 100],
266
+ index=[10, 20, 50, 100].index(page_size) if page_size in [10, 20, 50, 100] else 1,
267
+ key='page_size_selector',
268
+ )
269
+ if new_page_size != page_size:
270
+ st.session_state.page_size_value = new_page_size
271
+ st.session_state.current_page = 0 # Reset to first page
272
+ st.rerun()
273
+
274
+ def render_job_details(self, job):
275
+ """Render the job details page."""
276
+ job_id = job.get('id', 'Unknown')
277
+
278
+ # Check if we're viewing a different job and clear cached logs
279
+ if 'last_viewed_job_id' not in st.session_state or st.session_state['last_viewed_job_id'] != job_id:
280
+ # Clear cached logs and streaming state when switching to a different job
281
+ st.session_state.pop('job_logs_content', None)
282
+ st.session_state.pop('stream_counter', None)
283
+ st.session_state['last_viewed_job_id'] = job_id
284
+
285
+ # Try to get job name
286
+ job_name = (
287
+ job.get('name')
288
+ or job.get('display_name')
289
+ or job.get('action')
290
+ or (job.get('params', {}).get('name') if isinstance(job.get('params'), dict) else None)
291
+ or f'Job {str(job_id)[:8]}...'
292
+ )
293
+
294
+ # Header with back button
295
+ col1, col2 = st.columns([1, 4])
296
+ with col1:
297
+ if render_action_button('Back', key='back_to_jobs', icon='←', type='secondary'):
298
+ del st.session_state['selected_job']
299
+ st.rerun()
300
+ with col2:
301
+ render_section_header(job_name, f'ID: {job_id}')
302
+
303
+ # Status badge with spacing
304
+ status = job.get('status', 'Unknown')
305
+ st.markdown(f"<div style='margin: 12px 0;'>{get_status_badge_html(status)}</div>", unsafe_allow_html=True)
306
+
307
+ # Job Logs section (moved to top)
308
+ render_section_header('Job Logs')
309
+
310
+ # Add controls for logs
311
+ col1, col2, col3 = st.columns([1, 1, 2])
312
+ with col1:
313
+ st.checkbox(
314
+ 'Auto-scroll', value=True, key='logs_auto_scroll', disabled=True, help='Always scrolls to bottom'
315
+ )
316
+ with col2:
317
+ stream_logs = st.checkbox(
318
+ 'Auto-refresh', value=False, key='logs_stream', help='Refresh logs every 3 seconds'
319
+ )
320
+ with col3:
321
+ if st.button('Clear cache', key='clear_logs'):
322
+ st.session_state.pop('job_logs_content', None)
323
+
324
+ # Create log display area with CSS
325
+ log_css = """
326
+ <style>
327
+ .log-container {
328
+ background-color: #1e1e1e;
329
+ color: #d4d4d4;
330
+ font-family: 'Consolas', 'Monaco', 'Courier New', monospace;
331
+ font-size: 12px;
332
+ padding: 12px;
333
+ border-radius: 4px;
334
+ height: 500px;
335
+ overflow-y: auto;
336
+ overflow-x: auto;
337
+ white-space: pre;
338
+ }
339
+ .log-line {
340
+ display: flex;
341
+ line-height: 1.4;
342
+ padding: 2px 0;
343
+ }
344
+ .log-line:hover {
345
+ background-color: #2d2d2d;
346
+ }
347
+ .log-line-number {
348
+ color: #858585;
349
+ margin-right: 12px;
350
+ min-width: 40px;
351
+ text-align: right;
352
+ user-select: none;
353
+ }
354
+ .log-line-content {
355
+ flex: 1;
356
+ white-space: pre-wrap;
357
+ word-wrap: break-word;
358
+ }
359
+ .log-error {
360
+ color: #f48771;
361
+ }
362
+ .log-warning {
363
+ color: #dcdcaa;
364
+ }
365
+ .log-info {
366
+ color: #9cdcfe;
367
+ }
368
+ .log-debug {
369
+ color: #858585;
370
+ }
371
+ .log-timestamp {
372
+ color: #569cd6;
373
+ }
374
+ </style>
375
+ """
376
+ st.markdown(log_css, unsafe_allow_html=True)
377
+
378
+ # Display logs container
379
+ log_placeholder = st.empty()
380
+
381
+ # Control buttons
382
+ col1, col2 = st.columns([1, 3])
383
+ with col1:
384
+ if st.button('🔄 Refresh', key='refresh_logs'):
385
+ st.session_state.pop('job_logs_content', None)
386
+ st.rerun()
387
+
388
+ # Auto-refresh using JavaScript
389
+ if stream_logs:
390
+ with col2:
391
+ st.info('🔄 Auto-refresh enabled (every 3 seconds)')
392
+ # Add JavaScript to refresh the page every 3 seconds
393
+ st.markdown(
394
+ """
395
+ <script>
396
+ setTimeout(function() {
397
+ window.location.reload();
398
+ }, 3000);
399
+ </script>
400
+ """,
401
+ unsafe_allow_html=True,
402
+ )
403
+ # Clear cache for fresh logs on each refresh
404
+ st.session_state.pop('job_logs_content', None)
405
+
406
+ # Display logs
407
+ with log_placeholder.container():
408
+ try:
409
+ # Fetch logs if not cached
410
+ if 'job_logs_content' not in st.session_state:
411
+ with st.spinner('Fetching logs...'):
412
+ logs = []
413
+ for log_line in self.job_service.get_job_logs(job_id):
414
+ logs.append(log_line)
415
+ st.session_state['job_logs_content'] = logs
416
+
417
+ # Get logs from cache
418
+ logs = st.session_state.get('job_logs_content', [])
419
+
420
+ # Display logs
421
+ if logs:
422
+ formatted_logs = []
423
+ for i, line in enumerate(logs, 1):
424
+ formatted_logs.append(format_log_line(line, i))
425
+
426
+ logs_html = f'<div class="log-container" id="logContainer">{"".join(formatted_logs)}</div>'
427
+ st.markdown(logs_html, unsafe_allow_html=True)
428
+
429
+ # Always scroll to bottom when logs are displayed
430
+ st.markdown(
431
+ """
432
+ <script>
433
+ setTimeout(function() {
434
+ var logContainer = document.getElementById('logContainer');
435
+ if (logContainer) {
436
+ logContainer.scrollTop = logContainer.scrollHeight;
437
+ }
438
+ }, 100);
439
+ </script>
440
+ """,
441
+ unsafe_allow_html=True,
442
+ )
443
+ else:
444
+ st.info('No logs available for this job.')
445
+
446
+ except Exception as e:
447
+ st.error(f'Failed to fetch logs: {e}')
448
+
449
+ # Job Information section with better spacing
450
+ st.markdown("<div style='margin-top: 30px;'></div>", unsafe_allow_html=True)
451
+ render_section_header('Job Information')
452
+ col1, col2 = st.columns(2)
453
+
454
+ with col1:
455
+ st.markdown(
456
+ f"<div style='margin-bottom: 12px;'><strong>Job ID:</strong> <code>{job.get('id', 'N/A')}</code></div>",
457
+ unsafe_allow_html=True,
458
+ )
459
+ st.markdown(
460
+ f"<div style='margin-bottom: 12px;'><strong>Status:</strong> {job.get('status', 'N/A')}</div>",
461
+ unsafe_allow_html=True,
462
+ )
463
+ plugin_cat = job.get('plugin_category', 'N/A')
464
+ st.markdown(
465
+ f"<div style='margin-bottom: 12px;'><strong>Plugin Category:</strong> {plugin_cat}</div>",
466
+ unsafe_allow_html=True,
467
+ )
468
+ # Display agent info with enriched data
469
+ agent_id = job.get('agent', 'N/A')
470
+ agent_name = job.get('agent_name')
471
+ agent_url = job.get('agent_url')
472
+
473
+ if agent_name and agent_url:
474
+ agent_display = f'{agent_name} @ {agent_url}'
475
+ elif agent_name:
476
+ agent_display = agent_name
477
+ elif agent_url:
478
+ agent_display = agent_url
479
+ else:
480
+ agent_display = f'Agent #{agent_id}'
481
+
482
+ st.markdown(
483
+ f"<div style='margin-bottom: 12px;'><strong>Agent:</strong> {agent_display}</div>",
484
+ unsafe_allow_html=True,
485
+ )
486
+ # Display plugin info with enriched data
487
+ plugin_rel = job.get('plugin_release', 'N/A')
488
+ plugin_name = job.get('plugin_name') or job.get('plugin_code')
489
+ plugin_version = job.get('plugin_version')
490
+
491
+ if not plugin_name:
492
+ plugin_name = job.get('plugin_category')
493
+
494
+ if plugin_name and plugin_version:
495
+ plugin_display = f'{plugin_name} (v{plugin_version})'
496
+ elif plugin_name:
497
+ plugin_display = plugin_name
498
+ else:
499
+ plugin_display = f'Plugin #{plugin_rel}'
500
+
501
+ st.markdown(
502
+ f"<div style='margin-bottom: 12px;'><strong>Plugin:</strong> {plugin_display}</div>",
503
+ unsafe_allow_html=True,
504
+ )
505
+
506
+ with col2:
507
+ user = job.get('user', {})
508
+ user_name = user.get('name', user.get('email', 'N/A'))
509
+ st.markdown(
510
+ f"<div style='margin-bottom: 12px;'><strong>User:</strong> {user_name}</div>",
511
+ unsafe_allow_html=True,
512
+ )
513
+ st.markdown(
514
+ f"<div style='margin-bottom: 12px;'><strong>Created:</strong> {job.get('created', 'N/A')}</div>",
515
+ unsafe_allow_html=True,
516
+ )
517
+ completed = job.get('completed', 'N/A') if job.get('completed') else 'In Progress'
518
+ st.markdown(
519
+ f"<div style='margin-bottom: 12px;'><strong>Completed:</strong> {completed}</div>",
520
+ unsafe_allow_html=True,
521
+ )
522
+ progress = job.get('progress', {})
523
+ st.markdown(
524
+ f"<div style='margin-bottom: 12px;'><strong>Progress:</strong> {progress.get('overall', 0)}%</div>",
525
+ unsafe_allow_html=True,
526
+ )
527
+
528
+ # Calculate duration
529
+ duration_text = self.job_service.format_duration(job.get('created'), job.get('completed'))
530
+ if duration_text not in ['-', '...']:
531
+ st.markdown(
532
+ f"<div style='margin-bottom: 12px;'><strong>Duration:</strong> {duration_text}</div>",
533
+ unsafe_allow_html=True,
534
+ )
535
+
536
+ # Parameters section with spacing
537
+ if job.get('params'):
538
+ st.markdown("<div style='margin-top: 30px;'></div>", unsafe_allow_html=True)
539
+ params = job.get('params')
540
+ # Use table view for simple params, compact view for complex
541
+ if isinstance(params, dict) and all(not isinstance(v, (dict, list)) for v in params.values()):
542
+ render_json_as_table(params, 'Parameters')
543
+ else:
544
+ render_json_compact(params, 'Parameters')
545
+
546
+ # Result section with spacing
547
+ if job.get('result'):
548
+ st.markdown("<div style='margin-top: 30px;'></div>", unsafe_allow_html=True)
549
+ render_json_compact(job.get('result'), 'Result')
550
+
551
+ # Metrics section with spacing
552
+ metrics = job.get('metrics_by_categories')
553
+ if metrics and metrics != {}:
554
+ st.markdown("<div style='margin-top: 30px;'></div>", unsafe_allow_html=True)
555
+ # Use grid for simple metrics, compact view for nested
556
+ if isinstance(metrics, dict):
557
+ has_nested = any(isinstance(v, (dict, list)) for v in metrics.values())
558
+ if has_nested:
559
+ render_json_compact(metrics, 'Metrics by Categories')
560
+ else:
561
+ render_metrics_grid(metrics, 'Metrics')
562
+ else:
563
+ render_json_compact(metrics, 'Metrics')
564
+
565
+ # Detail section with spacing
566
+ detail = job.get('detail')
567
+ if detail and detail != {}:
568
+ st.markdown("<div style='margin-top: 30px;'></div>", unsafe_allow_html=True)
569
+ # Use table for simple details, compact for complex
570
+ if isinstance(detail, dict) and all(not isinstance(v, (dict, list)) for v in detail.values()):
571
+ render_json_as_table(detail, 'Additional Details')
572
+ else:
573
+ render_json_compact(detail, 'Additional Details')