sovara 0.2.6__tar.gz → 0.2.7__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 (214) hide show
  1. {sovara-0.2.6 → sovara-0.2.7}/PKG-INFO +1 -1
  2. {sovara-0.2.6 → sovara-0.2.7}/pyproject.toml +1 -1
  3. {sovara-0.2.6 → sovara-0.2.7}/src/sovara/runner/agent_runner.py +23 -12
  4. {sovara-0.2.6 → sovara-0.2.7}/src/sovara/runner/priors.py +66 -18
  5. {sovara-0.2.6 → sovara-0.2.7}/src/sovara/server/app.py +6 -1
  6. {sovara-0.2.6 → sovara-0.2.7}/src/sovara/server/database/llm_calls.py +10 -3
  7. {sovara-0.2.6 → sovara-0.2.7}/src/sovara/server/graph_models.py +35 -2
  8. {sovara-0.2.6 → sovara-0.2.7}/src/sovara/server/routes/claude_proxy.py +272 -65
  9. {sovara-0.2.6 → sovara-0.2.7}/src/sovara/server/routes/ui_runs.py +76 -18
  10. {sovara-0.2.6 → sovara-0.2.7}/src/sovara/server/state.py +58 -44
  11. {sovara-0.2.6 → sovara-0.2.7}/src/sovara.egg-info/PKG-INFO +1 -1
  12. {sovara-0.2.6 → sovara-0.2.7}/LICENSE +0 -0
  13. {sovara-0.2.6 → sovara-0.2.7}/README.md +0 -0
  14. {sovara-0.2.6 → sovara-0.2.7}/docs/release/PYPI_DESC.md +0 -0
  15. {sovara-0.2.6 → sovara-0.2.7}/setup.cfg +0 -0
  16. {sovara-0.2.6 → sovara-0.2.7}/src/sovara/__init__.py +0 -0
  17. {sovara-0.2.6 → sovara-0.2.7}/src/sovara/assets/SKILL.md +0 -0
  18. {sovara-0.2.6 → sovara-0.2.7}/src/sovara/assets/__init__.py +0 -0
  19. {sovara-0.2.6 → sovara-0.2.7}/src/sovara/assets/web_app/assets/AttachmentPreview-CFrNMdfC.css +0 -0
  20. {sovara-0.2.6 → sovara-0.2.7}/src/sovara/assets/web_app/assets/AttachmentPreview-Di2_OG_9.js +0 -0
  21. {sovara-0.2.6 → sovara-0.2.7}/src/sovara/assets/web_app/assets/DocumentPreviewModal-CvQFa4di.js +0 -0
  22. {sovara-0.2.6 → sovara-0.2.7}/src/sovara/assets/web_app/assets/LayoutBreadcrumb-CJhx8VyY.js +0 -0
  23. {sovara-0.2.6 → sovara-0.2.7}/src/sovara/assets/web_app/assets/LayoutBreadcrumb-CPgbqAJg.css +0 -0
  24. {sovara-0.2.6 → sovara-0.2.7}/src/sovara/assets/web_app/assets/OrgRoute-CKAmaA4W.js +0 -0
  25. {sovara-0.2.6 → sovara-0.2.7}/src/sovara/assets/web_app/assets/OrgRoute-Syy1k3se.css +0 -0
  26. {sovara-0.2.6 → sovara-0.2.7}/src/sovara/assets/web_app/assets/PriorsRoute-BveozA7x.css +0 -0
  27. {sovara-0.2.6 → sovara-0.2.7}/src/sovara/assets/web_app/assets/PriorsRoute-K5s0QhMy.js +0 -0
  28. {sovara-0.2.6 → sovara-0.2.7}/src/sovara/assets/web_app/assets/ProjectRoute-C3Jzk4jL.css +0 -0
  29. {sovara-0.2.6 → sovara-0.2.7}/src/sovara/assets/web_app/assets/ProjectRoute-djLnqcoS.js +0 -0
  30. {sovara-0.2.6 → sovara-0.2.7}/src/sovara/assets/web_app/assets/ProjectRunsRoute-ChqTPgDi.css +0 -0
  31. {sovara-0.2.6 → sovara-0.2.7}/src/sovara/assets/web_app/assets/ProjectRunsRoute-Df4n91j5.js +0 -0
  32. {sovara-0.2.6 → sovara-0.2.7}/src/sovara/assets/web_app/assets/RunRoute-BXKXUvYa.js +0 -0
  33. {sovara-0.2.6 → sovara-0.2.7}/src/sovara/assets/web_app/assets/RunRoute-CRAJ9hM9.css +0 -0
  34. {sovara-0.2.6 → sovara-0.2.7}/src/sovara/assets/web_app/assets/SettingsRoute-CJYubNN5.js +0 -0
  35. {sovara-0.2.6 → sovara-0.2.7}/src/sovara/assets/web_app/assets/arrow_lr-ByI2ndPB.png +0 -0
  36. {sovara-0.2.6 → sovara-0.2.7}/src/sovara/assets/web_app/assets/arrow_spiral_tr_bl-XHIpf338.png +0 -0
  37. {sovara-0.2.6 → sovara-0.2.7}/src/sovara/assets/web_app/assets/codicon-BYm2YbZ6.ttf +0 -0
  38. {sovara-0.2.6 → sovara-0.2.7}/src/sovara/assets/web_app/assets/eye-BwLFOixq.js +0 -0
  39. {sovara-0.2.6 → sovara-0.2.7}/src/sovara/assets/web_app/assets/index-Cu0VGrcx.js +0 -0
  40. {sovara-0.2.6 → sovara-0.2.7}/src/sovara/assets/web_app/assets/index-NbFqPLEC.css +0 -0
  41. {sovara-0.2.6 → sovara-0.2.7}/src/sovara/assets/web_app/assets/navigation-BBqqpNGD.js +0 -0
  42. {sovara-0.2.6 → sovara-0.2.7}/src/sovara/assets/web_app/assets/pdf.worker.min-qwK7q_zL.mjs +0 -0
  43. {sovara-0.2.6 → sovara-0.2.7}/src/sovara/assets/web_app/assets/plus-LepfYku6.js +0 -0
  44. {sovara-0.2.6 → sovara-0.2.7}/src/sovara/assets/web_app/assets/prismTheme-BK3YfG66.js +0 -0
  45. {sovara-0.2.6 → sovara-0.2.7}/src/sovara/assets/web_app/assets/runtime-CCiRiliL.css +0 -0
  46. {sovara-0.2.6 → sovara-0.2.7}/src/sovara/assets/web_app/assets/runtime-rMDdBrlz.js +0 -0
  47. {sovara-0.2.6 → sovara-0.2.7}/src/sovara/assets/web_app/assets/settings-BS_NcxJU.css +0 -0
  48. {sovara-0.2.6 → sovara-0.2.7}/src/sovara/assets/web_app/assets/settings-CP5l-jN0.js +0 -0
  49. {sovara-0.2.6 → sovara-0.2.7}/src/sovara/assets/web_app/assets/sovara_wordmark-CjkpVR0a.png +0 -0
  50. {sovara-0.2.6 → sovara-0.2.7}/src/sovara/assets/web_app/assets/tierState-CVxZC5KD.js +0 -0
  51. {sovara-0.2.6 → sovara-0.2.7}/src/sovara/assets/web_app/assets/tiny-invariant-BCXflckp.js +0 -0
  52. {sovara-0.2.6 → sovara-0.2.7}/src/sovara/assets/web_app/assets/trash-2-QBj_Tw9w.js +0 -0
  53. {sovara-0.2.6 → sovara-0.2.7}/src/sovara/assets/web_app/assets/useTheme-BfCfHZeA.js +0 -0
  54. {sovara-0.2.6 → sovara-0.2.7}/src/sovara/assets/web_app/assets/value-BlxarHmt.js +0 -0
  55. {sovara-0.2.6 → sovara-0.2.7}/src/sovara/assets/web_app/favicon.png +0 -0
  56. {sovara-0.2.6 → sovara-0.2.7}/src/sovara/assets/web_app/index.html +0 -0
  57. {sovara-0.2.6 → sovara-0.2.7}/src/sovara/assets/web_app/marketplace_icon.png +0 -0
  58. {sovara-0.2.6 → sovara-0.2.7}/src/sovara/cli/__init__.py +0 -0
  59. {sovara-0.2.6 → sovara-0.2.7}/src/sovara/cli/so_config.py +0 -0
  60. {sovara-0.2.6 → sovara-0.2.7}/src/sovara/cli/so_record.py +0 -0
  61. {sovara-0.2.6 → sovara-0.2.7}/src/sovara/cli/so_server.py +0 -0
  62. {sovara-0.2.6 → sovara-0.2.7}/src/sovara/cli/so_tool.py +0 -0
  63. {sovara-0.2.6 → sovara-0.2.7}/src/sovara/common/__init__.py +0 -0
  64. {sovara-0.2.6 → sovara-0.2.7}/src/sovara/common/config.py +0 -0
  65. {sovara-0.2.6 → sovara-0.2.7}/src/sovara/common/constants.py +0 -0
  66. {sovara-0.2.6 → sovara-0.2.7}/src/sovara/common/custom_metrics.py +0 -0
  67. {sovara-0.2.6 → sovara-0.2.7}/src/sovara/common/lifecycle.py +0 -0
  68. {sovara-0.2.6 → sovara-0.2.7}/src/sovara/common/log_redaction.py +0 -0
  69. {sovara-0.2.6 → sovara-0.2.7}/src/sovara/common/logger.py +0 -0
  70. {sovara-0.2.6 → sovara-0.2.7}/src/sovara/common/priors_block.py +0 -0
  71. {sovara-0.2.6 → sovara-0.2.7}/src/sovara/common/project.py +0 -0
  72. {sovara-0.2.6 → sovara-0.2.7}/src/sovara/common/runtime.py +0 -0
  73. {sovara-0.2.6 → sovara-0.2.7}/src/sovara/common/user.py +0 -0
  74. {sovara-0.2.6 → sovara-0.2.7}/src/sovara/common/utils.py +0 -0
  75. {sovara-0.2.6 → sovara-0.2.7}/src/sovara/runner/__init__.py +0 -0
  76. {sovara-0.2.6 → sovara-0.2.7}/src/sovara/runner/context_manager.py +0 -0
  77. {sovara-0.2.6 → sovara-0.2.7}/src/sovara/runner/monkey_patching/__init__.py +0 -0
  78. {sovara-0.2.6 → sovara-0.2.7}/src/sovara/runner/monkey_patching/api_parser.py +0 -0
  79. {sovara-0.2.6 → sovara-0.2.7}/src/sovara/runner/monkey_patching/api_parsers/__init__.py +0 -0
  80. {sovara-0.2.6 → sovara-0.2.7}/src/sovara/runner/monkey_patching/api_parsers/aiohttp_api_parser.py +0 -0
  81. {sovara-0.2.6 → sovara-0.2.7}/src/sovara/runner/monkey_patching/api_parsers/claude_code_messages_api_parser.py +0 -0
  82. {sovara-0.2.6 → sovara-0.2.7}/src/sovara/runner/monkey_patching/api_parsers/httpx_api_parser.py +0 -0
  83. {sovara-0.2.6 → sovara-0.2.7}/src/sovara/runner/monkey_patching/api_parsers/mcp_api_parser.py +0 -0
  84. {sovara-0.2.6 → sovara-0.2.7}/src/sovara/runner/monkey_patching/api_parsers/requests_api_parser.py +0 -0
  85. {sovara-0.2.6 → sovara-0.2.7}/src/sovara/runner/monkey_patching/api_parsers/sse_utils.py +0 -0
  86. {sovara-0.2.6 → sovara-0.2.7}/src/sovara/runner/monkey_patching/api_parsers/urllib3_api_parser.py +0 -0
  87. {sovara-0.2.6 → sovara-0.2.7}/src/sovara/runner/monkey_patching/apply_monkey_patches.py +0 -0
  88. {sovara-0.2.6 → sovara-0.2.7}/src/sovara/runner/monkey_patching/async_streaming.py +0 -0
  89. {sovara-0.2.6 → sovara-0.2.7}/src/sovara/runner/monkey_patching/edit_io_filters.py +0 -0
  90. {sovara-0.2.6 → sovara-0.2.7}/src/sovara/runner/monkey_patching/endpoint_whitelist.py +0 -0
  91. {sovara-0.2.6 → sovara-0.2.7}/src/sovara/runner/monkey_patching/node_naming.py +0 -0
  92. {sovara-0.2.6 → sovara-0.2.7}/src/sovara/runner/monkey_patching/patches/__init__.py +0 -0
  93. {sovara-0.2.6 → sovara-0.2.7}/src/sovara/runner/monkey_patching/patches/adk_patch.py +0 -0
  94. {sovara-0.2.6 → sovara-0.2.7}/src/sovara/runner/monkey_patching/patches/aiohttp_patch.py +0 -0
  95. {sovara-0.2.6 → sovara-0.2.7}/src/sovara/runner/monkey_patching/patches/claude_sdk_patch.py +0 -0
  96. {sovara-0.2.6 → sovara-0.2.7}/src/sovara/runner/monkey_patching/patches/httpx_patch.py +0 -0
  97. {sovara-0.2.6 → sovara-0.2.7}/src/sovara/runner/monkey_patching/patches/langchain_patch.py +0 -0
  98. {sovara-0.2.6 → sovara-0.2.7}/src/sovara/runner/monkey_patching/patches/mcp_patches.py +0 -0
  99. {sovara-0.2.6 → sovara-0.2.7}/src/sovara/runner/monkey_patching/patches/openai_agents_patch.py +0 -0
  100. {sovara-0.2.6 → sovara-0.2.7}/src/sovara/runner/monkey_patching/patches/randomness_patch.py +0 -0
  101. {sovara-0.2.6 → sovara-0.2.7}/src/sovara/runner/monkey_patching/patches/requests_patch.py +0 -0
  102. {sovara-0.2.6 → sovara-0.2.7}/src/sovara/runner/monkey_patching/patches/urllib3_patch.py +0 -0
  103. {sovara-0.2.6 → sovara-0.2.7}/src/sovara/runner/monkey_patching/patching_utils.py +0 -0
  104. {sovara-0.2.6 → sovara-0.2.7}/src/sovara/runner/monkey_patching/tool_trace_utils.py +0 -0
  105. {sovara-0.2.6 → sovara-0.2.7}/src/sovara/runner/node_execution.py +0 -0
  106. {sovara-0.2.6 → sovara-0.2.7}/src/sovara/runner/priors_pipeline.py +0 -0
  107. {sovara-0.2.6 → sovara-0.2.7}/src/sovara/runner/run_log_capture.py +0 -0
  108. {sovara-0.2.6 → sovara-0.2.7}/src/sovara/runner/runtime_client.py +0 -0
  109. {sovara-0.2.6 → sovara-0.2.7}/src/sovara/runner/string_matching.py +0 -0
  110. {sovara-0.2.6 → sovara-0.2.7}/src/sovara/server/__init__.py +0 -0
  111. {sovara-0.2.6 → sovara-0.2.7}/src/sovara/server/claude_proxy_utils.py +0 -0
  112. {sovara-0.2.6 → sovara-0.2.7}/src/sovara/server/database/__init__.py +0 -0
  113. {sovara-0.2.6 → sovara-0.2.7}/src/sovara/server/database/_shared.py +0 -0
  114. {sovara-0.2.6 → sovara-0.2.7}/src/sovara/server/database/backend_protocol.py +0 -0
  115. {sovara-0.2.6 → sovara-0.2.7}/src/sovara/server/database/blob_storage.py +0 -0
  116. {sovara-0.2.6 → sovara-0.2.7}/src/sovara/server/database/manager.py +0 -0
  117. {sovara-0.2.6 → sovara-0.2.7}/src/sovara/server/database/mongodb/__init__.py +0 -0
  118. {sovara-0.2.6 → sovara-0.2.7}/src/sovara/server/database/mongodb/backend.py +0 -0
  119. {sovara-0.2.6 → sovara-0.2.7}/src/sovara/server/database/mongodb/connection.py +0 -0
  120. {sovara-0.2.6 → sovara-0.2.7}/src/sovara/server/database/postgresql/__init__.py +0 -0
  121. {sovara-0.2.6 → sovara-0.2.7}/src/sovara/server/database/postgresql/backend.py +0 -0
  122. {sovara-0.2.6 → sovara-0.2.7}/src/sovara/server/database/postgresql/connection.py +0 -0
  123. {sovara-0.2.6 → sovara-0.2.7}/src/sovara/server/database/postgresql/schema.py +0 -0
  124. {sovara-0.2.6 → sovara-0.2.7}/src/sovara/server/database/priors.py +0 -0
  125. {sovara-0.2.6 → sovara-0.2.7}/src/sovara/server/database/projects.py +0 -0
  126. {sovara-0.2.6 → sovara-0.2.7}/src/sovara/server/database/runs.py +0 -0
  127. {sovara-0.2.6 → sovara-0.2.7}/src/sovara/server/database/sqlite/__init__.py +0 -0
  128. {sovara-0.2.6 → sovara-0.2.7}/src/sovara/server/database/sqlite/backend.py +0 -0
  129. {sovara-0.2.6 → sovara-0.2.7}/src/sovara/server/database/sqlite/connection.py +0 -0
  130. {sovara-0.2.6 → sovara-0.2.7}/src/sovara/server/database/sqlite/llm_calls.py +0 -0
  131. {sovara-0.2.6 → sovara-0.2.7}/src/sovara/server/database/sqlite/priors.py +0 -0
  132. {sovara-0.2.6 → sovara-0.2.7}/src/sovara/server/database/sqlite/projects.py +0 -0
  133. {sovara-0.2.6 → sovara-0.2.7}/src/sovara/server/database/sqlite/runs.py +0 -0
  134. {sovara-0.2.6 → sovara-0.2.7}/src/sovara/server/database/sqlite/schema.py +0 -0
  135. {sovara-0.2.6 → sovara-0.2.7}/src/sovara/server/database/sqlite/users.py +0 -0
  136. {sovara-0.2.6 → sovara-0.2.7}/src/sovara/server/database/users.py +0 -0
  137. {sovara-0.2.6 → sovara-0.2.7}/src/sovara/server/graph_analysis/inference_server.py +0 -0
  138. {sovara-0.2.6 → sovara-0.2.7}/src/sovara/server/graph_analysis/trace_chat/__init__.py +0 -0
  139. {sovara-0.2.6 → sovara-0.2.7}/src/sovara/server/graph_analysis/trace_chat/cancel.py +0 -0
  140. {sovara-0.2.6 → sovara-0.2.7}/src/sovara/server/graph_analysis/trace_chat/main.py +0 -0
  141. {sovara-0.2.6 → sovara-0.2.7}/src/sovara/server/graph_analysis/trace_chat/tools/__init__.py +0 -0
  142. {sovara-0.2.6 → sovara-0.2.7}/src/sovara/server/graph_analysis/trace_chat/tools/ask_step.py +0 -0
  143. {sovara-0.2.6 → sovara-0.2.7}/src/sovara/server/graph_analysis/trace_chat/tools/edit_content.py +0 -0
  144. {sovara-0.2.6 → sovara-0.2.7}/src/sovara/server/graph_analysis/trace_chat/tools/get_step_overview.py +0 -0
  145. {sovara-0.2.6 → sovara-0.2.7}/src/sovara/server/graph_analysis/trace_chat/tools/get_step_snapshot.py +0 -0
  146. {sovara-0.2.6 → sovara-0.2.7}/src/sovara/server/graph_analysis/trace_chat/tools/get_trace_overview.py +0 -0
  147. {sovara-0.2.6 → sovara-0.2.7}/src/sovara/server/graph_analysis/trace_chat/tools/search.py +0 -0
  148. {sovara-0.2.6 → sovara-0.2.7}/src/sovara/server/graph_analysis/trace_chat/tools/summarize_trace.py +0 -0
  149. {sovara-0.2.6 → sovara-0.2.7}/src/sovara/server/graph_analysis/trace_chat/tools/verify.py +0 -0
  150. {sovara-0.2.6 → sovara-0.2.7}/src/sovara/server/graph_analysis/trace_chat/utils/__init__.py +0 -0
  151. {sovara-0.2.6 → sovara-0.2.7}/src/sovara/server/graph_analysis/trace_chat/utils/content_utils.py +0 -0
  152. {sovara-0.2.6 → sovara-0.2.7}/src/sovara/server/graph_analysis/trace_chat/utils/context.py +0 -0
  153. {sovara-0.2.6 → sovara-0.2.7}/src/sovara/server/graph_analysis/trace_chat/utils/edit_persist.py +0 -0
  154. {sovara-0.2.6 → sovara-0.2.7}/src/sovara/server/graph_analysis/trace_chat/utils/step_content_view.py +0 -0
  155. {sovara-0.2.6 → sovara-0.2.7}/src/sovara/server/graph_analysis/trace_chat/utils/step_ids.py +0 -0
  156. {sovara-0.2.6 → sovara-0.2.7}/src/sovara/server/graph_analysis/trace_chat/utils/trace.py +0 -0
  157. {sovara-0.2.6 → sovara-0.2.7}/src/sovara/server/graph_analysis/trace_chat/utils/verdict_persist.py +0 -0
  158. {sovara-0.2.6 → sovara-0.2.7}/src/sovara/server/handlers/__init__.py +0 -0
  159. {sovara-0.2.6 → sovara-0.2.7}/src/sovara/server/handlers/cli_handlers.py +0 -0
  160. {sovara-0.2.6 → sovara-0.2.7}/src/sovara/server/handlers/handler_utils.py +0 -0
  161. {sovara-0.2.6 → sovara-0.2.7}/src/sovara/server/handlers/runner_handlers.py +0 -0
  162. {sovara-0.2.6 → sovara-0.2.7}/src/sovara/server/handlers/ui_handlers.py +0 -0
  163. {sovara-0.2.6 → sovara-0.2.7}/src/sovara/server/llm_backend.py +0 -0
  164. {sovara-0.2.6 → sovara-0.2.7}/src/sovara/server/llm_provider_catalog.py +0 -0
  165. {sovara-0.2.6 → sovara-0.2.7}/src/sovara/server/llm_settings.py +0 -0
  166. {sovara-0.2.6 → sovara-0.2.7}/src/sovara/server/llm_settings_verification.py +0 -0
  167. {sovara-0.2.6 → sovara-0.2.7}/src/sovara/server/package_version.py +0 -0
  168. {sovara-0.2.6 → sovara-0.2.7}/src/sovara/server/prior_display.py +0 -0
  169. {sovara-0.2.6 → sovara-0.2.7}/src/sovara/server/priors_backend/__init__.py +0 -0
  170. {sovara-0.2.6 → sovara-0.2.7}/src/sovara/server/priors_backend/constants.py +0 -0
  171. {sovara-0.2.6 → sovara-0.2.7}/src/sovara/server/priors_backend/events.py +0 -0
  172. {sovara-0.2.6 → sovara-0.2.7}/src/sovara/server/priors_backend/llm/__init__.py +0 -0
  173. {sovara-0.2.6 → sovara-0.2.7}/src/sovara/server/priors_backend/llm/folder_rebalancer.py +0 -0
  174. {sovara-0.2.6 → sovara-0.2.7}/src/sovara/server/priors_backend/llm/lesson_restructurer.py +0 -0
  175. {sovara-0.2.6 → sovara-0.2.7}/src/sovara/server/priors_backend/llm/lesson_retriever.py +0 -0
  176. {sovara-0.2.6 → sovara-0.2.7}/src/sovara/server/priors_backend/llm/lesson_summarizer.py +0 -0
  177. {sovara-0.2.6 → sovara-0.2.7}/src/sovara/server/priors_backend/llm/lesson_validator.py +0 -0
  178. {sovara-0.2.6 → sovara-0.2.7}/src/sovara/server/priors_backend/llm/prior_metadata_suggester.py +0 -0
  179. {sovara-0.2.6 → sovara-0.2.7}/src/sovara/server/priors_backend/llm_client.py +0 -0
  180. {sovara-0.2.6 → sovara-0.2.7}/src/sovara/server/priors_backend/logger.py +0 -0
  181. {sovara-0.2.6 → sovara-0.2.7}/src/sovara/server/priors_backend/path_utils.py +0 -0
  182. {sovara-0.2.6 → sovara-0.2.7}/src/sovara/server/priors_backend/retrieval_service.py +0 -0
  183. {sovara-0.2.6 → sovara-0.2.7}/src/sovara/server/priors_backend/routes.py +0 -0
  184. {sovara-0.2.6 → sovara-0.2.7}/src/sovara/server/priors_backend/storage.py +0 -0
  185. {sovara-0.2.6 → sovara-0.2.7}/src/sovara/server/priors_backend/tools/adjudication.py +0 -0
  186. {sovara-0.2.6 → sovara-0.2.7}/src/sovara/server/priors_backend/tools/bm25_search.py +0 -0
  187. {sovara-0.2.6 → sovara-0.2.7}/src/sovara/server/priors_backend/tools/dense_search.py +0 -0
  188. {sovara-0.2.6 → sovara-0.2.7}/src/sovara/server/priors_backend/tools/folder_groups.py +0 -0
  189. {sovara-0.2.6 → sovara-0.2.7}/src/sovara/server/priors_backend/tools/keyword_search.py +0 -0
  190. {sovara-0.2.6 → sovara-0.2.7}/src/sovara/server/priors_backend/tools/parallel_search.py +0 -0
  191. {sovara-0.2.6 → sovara-0.2.7}/src/sovara/server/priors_backend/tools/preprocess_context.py +0 -0
  192. {sovara-0.2.6 → sovara-0.2.7}/src/sovara/server/priors_backend/tools/prior_adherence.py +0 -0
  193. {sovara-0.2.6 → sovara-0.2.7}/src/sovara/server/priors_backend/tools/prior_coverage.py +0 -0
  194. {sovara-0.2.6 → sovara-0.2.7}/src/sovara/server/priors_backend/tools/rerank.py +0 -0
  195. {sovara-0.2.6 → sovara-0.2.7}/src/sovara/server/priors_backend/tools/utils.py +0 -0
  196. {sovara-0.2.6 → sovara-0.2.7}/src/sovara/server/priors_scope.py +0 -0
  197. {sovara-0.2.6 → sovara-0.2.7}/src/sovara/server/routes/__init__.py +0 -0
  198. {sovara-0.2.6 → sovara-0.2.7}/src/sovara/server/routes/events.py +0 -0
  199. {sovara-0.2.6 → sovara-0.2.7}/src/sovara/server/routes/internal.py +0 -0
  200. {sovara-0.2.6 → sovara-0.2.7}/src/sovara/server/routes/runner.py +0 -0
  201. {sovara-0.2.6 → sovara-0.2.7}/src/sovara/server/routes/ui.py +0 -0
  202. {sovara-0.2.6 → sovara-0.2.7}/src/sovara/server/routes/ui_common.py +0 -0
  203. {sovara-0.2.6 → sovara-0.2.7}/src/sovara/server/routes/ui_projects.py +0 -0
  204. {sovara-0.2.6 → sovara-0.2.7}/src/sovara/server/routes/ui_trace_chat.py +0 -0
  205. {sovara-0.2.6 → sovara-0.2.7}/src/sovara/server/services/__init__.py +0 -0
  206. {sovara-0.2.6 → sovara-0.2.7}/src/sovara/server/services/trace_chat_service.py +0 -0
  207. {sovara-0.2.6 → sovara-0.2.7}/src/sovara/server/third_party_model_catalog.py +0 -0
  208. {sovara-0.2.6 → sovara-0.2.7}/src/sovara/server/web_app_assets.py +0 -0
  209. {sovara-0.2.6 → sovara-0.2.7}/src/sovara.egg-info/SOURCES.txt +0 -0
  210. {sovara-0.2.6 → sovara-0.2.7}/src/sovara.egg-info/dependency_links.txt +0 -0
  211. {sovara-0.2.6 → sovara-0.2.7}/src/sovara.egg-info/entry_points.txt +0 -0
  212. {sovara-0.2.6 → sovara-0.2.7}/src/sovara.egg-info/requires.txt +0 -0
  213. {sovara-0.2.6 → sovara-0.2.7}/src/sovara.egg-info/top_level.txt +0 -0
  214. {sovara-0.2.6 → sovara-0.2.7}/tests/test_graph_payloads.py +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: sovara
3
- Version: 0.2.6
3
+ Version: 0.2.7
4
4
  Summary: A development tool for LLM call visualization and debugging
5
5
  Requires-Python: >=3.10
6
6
  Description-Content-Type: text/markdown
@@ -26,7 +26,7 @@ line-length = 100
26
26
 
27
27
  [project]
28
28
  name = "sovara"
29
- version = "0.2.6"
29
+ version = "0.2.7"
30
30
  description = "A development tool for LLM call visualization and debugging"
31
31
  readme = "docs/release/PYPI_DESC.md"
32
32
  requires-python = ">=3.10"
@@ -245,16 +245,29 @@ def _check_server_health() -> bool:
245
245
  """Check if the server is healthy via HTTP."""
246
246
  import httpx
247
247
 
248
+ expected_python = os.path.realpath(sys.executable)
248
249
  try:
249
250
  resp = httpx.get(f"http://{HOST}:{PORT}/health", timeout=SERVER_START_TIMEOUT)
250
251
  if resp.status_code != 200:
251
252
  return False
252
253
  payload = resp.json()
253
- return (
254
+ if not (
254
255
  isinstance(payload, dict)
255
256
  and payload.get("status") == "ok"
256
257
  and payload.get("service") == "sovara"
257
- )
258
+ ):
259
+ return False
260
+ server_python = payload.get("python_executable")
261
+ if not server_python:
262
+ logger.warning("Sovara server health response is missing python_executable.")
263
+ return False
264
+ if os.path.realpath(str(server_python)) != expected_python:
265
+ logger.warning(
266
+ "Sovara server is running under a different Python executable "
267
+ f"({server_python}); expected {sys.executable}."
268
+ )
269
+ return False
270
+ return True
258
271
  except Exception:
259
272
  return False
260
273
 
@@ -265,11 +278,13 @@ def ensure_server_running() -> None:
265
278
  logger.debug(f"Server already running on {HOST}:{PORT}")
266
279
  return
267
280
 
268
- # Check for zombie process
269
- zombie_pid = _find_process_on_port(PORT)
270
- if zombie_pid:
271
- logger.warning(f"Found unresponsive server process {zombie_pid}, killing it...")
272
- if _kill_zombie_server(zombie_pid):
281
+ # Check for an unresponsive or incompatible server process.
282
+ existing_pid = _find_process_on_port(PORT)
283
+ if existing_pid:
284
+ logger.warning(
285
+ f"Found unresponsive or incompatible server process {existing_pid}, killing it..."
286
+ )
287
+ if _kill_zombie_server(existing_pid):
273
288
  time.sleep(1)
274
289
 
275
290
  # Launch new daemon
@@ -553,11 +568,7 @@ class AgentRunner:
553
568
  def _register_with_server(self) -> None:
554
569
  """Register with the server via HTTP POST."""
555
570
  logger.info(f"[AgentRunner] Registering with server at {self.server_url}...")
556
- prev_run_id = (
557
- os.getenv("SOVARA_RUN_ID")
558
- if os.getenv(_REUSE_RUN_ID_ENV) == "1"
559
- else None
560
- )
571
+ prev_run_id = os.getenv("SOVARA_RUN_ID") if os.getenv(_REUSE_RUN_ID_ENV) == "1" else None
561
572
 
562
573
  response = http_post(
563
574
  "/runner/register",
@@ -240,7 +240,16 @@ def restore_input_after_call(prior_result: PriorPreparationResult | None) -> Ite
240
240
 
241
241
 
242
242
  def prepare_llm_call_for_priors(
243
- input_dict: dict[str, Any], api_type: str
243
+ input_dict: dict[str, Any],
244
+ api_type: str,
245
+ *,
246
+ lookup_prefix_cache_func: (
247
+ Callable[[str, list[dict[str, str]]], tuple[dict[str, Any] | None, int]] | None
248
+ ) = None,
249
+ store_prefix_cache_func: (
250
+ Callable[[str | None, list[dict[str, str]], list[dict[str, str]], list[str]], None] | None
251
+ ) = None,
252
+ retrieve_priors_func: Callable[[str, str, list[str]], dict[str, Any]] | None = None,
244
253
  ) -> PriorPreparationResult:
245
254
  run_id = get_run_id()
246
255
  complete_json_str = func_kwargs_to_json_str(input_dict, api_type)
@@ -283,9 +292,23 @@ def prepare_llm_call_for_priors(
283
292
  matched_prefix_len = 0
284
293
  working_flattened = dict(cleaned_flattened)
285
294
  if run_id and clean_content_pairs:
286
- prefix_entry, matched_prefix_len = _lookup_longest_prefix_cache_hit(
287
- run_id, clean_content_pairs
288
- )
295
+ if lookup_prefix_cache_func is not None:
296
+ try:
297
+ prefix_entry, matched_prefix_len = lookup_prefix_cache_func(
298
+ run_id, clean_content_pairs
299
+ )
300
+ except Exception as exc:
301
+ _log_priors(
302
+ "automatic",
303
+ "warning",
304
+ "[PRIORS RUNTIME] prefix lookup failed",
305
+ error=str(exc),
306
+ )
307
+ prefix_entry, matched_prefix_len = None, 0
308
+ else:
309
+ prefix_entry, matched_prefix_len = _lookup_longest_prefix_cache_hit(
310
+ run_id, clean_content_pairs
311
+ )
289
312
  if prefix_entry is not None:
290
313
  working_flattened = replay_injected_prefix(
291
314
  cleaned_flattened,
@@ -387,14 +410,22 @@ def prepare_llm_call_for_priors(
387
410
  run_id=run_id,
388
411
  ignore_ids=inherited_prior_ids,
389
412
  )
390
- response = http_post(
391
- "/internal/priors/retrieve",
392
- {
393
- "run_id": run_id,
394
- "raw_context": raw_context,
395
- "ignore_prior_ids": inherited_prior_ids,
396
- },
397
- timeout=_INTERNAL_PRIORS_HTTP_TIMEOUT_S,
413
+ response = (
414
+ http_post(
415
+ "/internal/priors/retrieve",
416
+ {
417
+ "run_id": run_id,
418
+ "raw_context": raw_context,
419
+ "ignore_prior_ids": inherited_prior_ids,
420
+ },
421
+ timeout=_INTERNAL_PRIORS_HTTP_TIMEOUT_S,
422
+ )
423
+ if retrieve_priors_func is None
424
+ else retrieve_priors_func(
425
+ run_id,
426
+ raw_context,
427
+ inherited_prior_ids,
428
+ )
398
429
  )
399
430
  metadata.retrieval_latency_ms = int((time.perf_counter() - started_at) * 1000)
400
431
  metadata.retrieval_id = response.get("retrieval_id")
@@ -430,12 +461,29 @@ def prepare_llm_call_for_priors(
430
461
  if isinstance(prior.get("id"), str) and prior.get("id")
431
462
  ]
432
463
  )
433
- _store_prefix_cache_entry(
434
- run_id,
435
- clean_content_pairs,
436
- extract_content_bearing_pairs(executed_flattened, api_type),
437
- effective_prior_ids,
438
- )
464
+ injected_pairs = extract_content_bearing_pairs(executed_flattened, api_type)
465
+ if store_prefix_cache_func is not None:
466
+ try:
467
+ store_prefix_cache_func(
468
+ run_id,
469
+ clean_content_pairs,
470
+ injected_pairs,
471
+ effective_prior_ids,
472
+ )
473
+ except Exception as exc:
474
+ _log_priors(
475
+ "automatic",
476
+ "warning",
477
+ "[PRIORS RUNTIME] prefix store failed",
478
+ error=str(exc),
479
+ )
480
+ else:
481
+ _store_prefix_cache_entry(
482
+ run_id,
483
+ clean_content_pairs,
484
+ injected_pairs,
485
+ effective_prior_ids,
486
+ )
439
487
  return _build_result(executed_flattened)
440
488
  except httpx.TimeoutException as exc:
441
489
  _mark_retrieval_failure(
@@ -5,6 +5,7 @@ FastAPI application factory.
5
5
  import asyncio
6
6
  import json
7
7
  import os
8
+ import sys
8
9
  from contextlib import asynccontextmanager
9
10
  from pathlib import Path
10
11
 
@@ -232,7 +233,11 @@ def create_app() -> FastAPI:
232
233
 
233
234
  @app.get("/health")
234
235
  async def health():
235
- return {"status": "ok", "service": "sovara"}
236
+ return {
237
+ "status": "ok",
238
+ "service": "sovara",
239
+ "python_executable": sys.executable,
240
+ }
236
241
 
237
242
  @app.get("/", include_in_schema=False)
238
243
  async def web_app_index():
@@ -1,3 +1,4 @@
1
+ from collections.abc import Callable
1
2
  import json
2
3
  import random
3
4
  import time
@@ -223,6 +224,7 @@ class LlmCallsMixin:
223
224
  api_type: str,
224
225
  *,
225
226
  prepare_runtime_priors: bool = False,
227
+ prior_preparer: Callable[[dict, str], Any] | None = None,
226
228
  ) -> CacheOutput:
227
229
  """Get input/output for an LLM call, handling caching, overwrites, and priors."""
228
230
  from sovara.common.utils import hash_input, set_seed
@@ -247,7 +249,8 @@ class LlmCallsMixin:
247
249
  if should_prepare_runtime_priors:
248
250
  from sovara.runner.priors import prepare_llm_call_for_priors
249
251
 
250
- prior_result = prepare_llm_call_for_priors(input_dict, api_type)
252
+ preparer = prior_preparer or prepare_llm_call_for_priors
253
+ prior_result = preparer(input_dict, api_type)
251
254
  working_input_dict = prior_result.executed_input_dict
252
255
 
253
256
  input_pickle = func_kwargs_to_json_str(working_input_dict, api_type)
@@ -305,7 +308,8 @@ class LlmCallsMixin:
305
308
  if should_prepare_runtime_priors:
306
309
  from sovara.runner.priors import prepare_llm_call_for_priors
307
310
 
308
- prior_result = prepare_llm_call_for_priors(working_input_dict, api_type)
311
+ preparer = prior_preparer or prepare_llm_call_for_priors
312
+ prior_result = preparer(working_input_dict, api_type)
309
313
  prior_result.restore_original_input = restore_original_transport_input
310
314
  working_input_dict = prior_result.executed_input_dict
311
315
  input_pickle = func_kwargs_to_json_str(working_input_dict, api_type)
@@ -554,6 +558,9 @@ class LlmCallsMixin:
554
558
 
555
559
  def get_tokens_timeseries(self, project_id, time_from, time_to, bucket_seconds):
556
560
  return self.backend.get_tokens_timeseries_query(
557
- project_id, time_from, time_to, bucket_seconds,
561
+ project_id,
562
+ time_from,
563
+ time_to,
564
+ bucket_seconds,
558
565
  user_id=self.user_id,
559
566
  )
@@ -30,7 +30,9 @@ class IncomingNode:
30
30
  input=str(data["input"]),
31
31
  output=str(data["output"]),
32
32
  label=str(data["label"]),
33
- latency_seconds=None if data.get("latency_seconds") is None else float(data["latency_seconds"]),
33
+ latency_seconds=(
34
+ None if data.get("latency_seconds") is None else float(data["latency_seconds"])
35
+ ),
34
36
  status=None if data.get("status") is None else str(data["status"]),
35
37
  error_message=None if data.get("error_message") is None else str(data["error_message"]),
36
38
  llm_verdict=None if data.get("llm_verdict") is None else str(data["llm_verdict"]),
@@ -82,7 +84,9 @@ class GraphNode:
82
84
  input=str(data["input"]),
83
85
  output=str(data["output"]),
84
86
  label=str(data["label"]),
85
- latency_seconds=None if data.get("latency_seconds") is None else float(data["latency_seconds"]),
87
+ latency_seconds=(
88
+ None if data.get("latency_seconds") is None else float(data["latency_seconds"])
89
+ ),
86
90
  status=None if data.get("status") is None else str(data["status"]),
87
91
  error_message=None if data.get("error_message") is None else str(data["error_message"]),
88
92
  llm_verdict=None if data.get("llm_verdict") is None else str(data["llm_verdict"]),
@@ -112,6 +116,28 @@ class GraphNode:
112
116
  payload["llm_verdict"] = self.llm_verdict
113
117
  return payload
114
118
 
119
+ def to_metadata_dict(self) -> dict[str, Any]:
120
+ payload = {
121
+ "uuid": self.uuid,
122
+ "step_id": self.step_id,
123
+ "label": self.label,
124
+ "node_kind": self.node_kind,
125
+ "raw_node_name": self.raw_node_name,
126
+ "has_input": bool(self.input),
127
+ "has_output": bool(self.output),
128
+ "input_size": len(self.input or ""),
129
+ "output_size": len(self.output or ""),
130
+ }
131
+ if self.latency_seconds is not None:
132
+ payload["latency_seconds"] = self.latency_seconds
133
+ if self.status is not None:
134
+ payload["status"] = self.status
135
+ if self.error_message is not None:
136
+ payload["error_message"] = self.error_message
137
+ if self.llm_verdict is not None:
138
+ payload["llm_verdict"] = self.llm_verdict
139
+ return payload
140
+
115
141
 
116
142
  @dataclass(slots=True)
117
143
  class GraphEdge:
@@ -163,11 +189,18 @@ class RunGraph:
163
189
  "edges": [edge.to_dict() for edge in self.edges],
164
190
  }
165
191
 
192
+ def to_metadata_dict(self) -> dict[str, Any]:
193
+ return {
194
+ "nodes": [node.to_metadata_dict() for node in self.nodes],
195
+ "edges": [edge.to_dict() for edge in self.edges],
196
+ }
197
+
166
198
  @classmethod
167
199
  def from_json_string(cls, data: str | None) -> "RunGraph":
168
200
  if not data:
169
201
  return cls.empty()
170
202
  from sovara.server.database.blob_storage import restore # lazy to avoid circular import
203
+
171
204
  return cls.from_dict(json.loads(restore(data)))
172
205
 
173
206
  def to_json_string(self) -> str: