virtual-context 0.3.5__tar.gz → 0.3.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 (250) hide show
  1. {virtual_context-0.3.5 → virtual_context-0.3.7}/.github/workflows/python-publish.yml +4 -2
  2. {virtual_context-0.3.5 → virtual_context-0.3.7}/PKG-INFO +1 -1
  3. {virtual_context-0.3.5 → virtual_context-0.3.7}/pyproject.toml +1 -1
  4. {virtual_context-0.3.5 → virtual_context-0.3.7}/tests/test_assembler.py +31 -1
  5. virtual_context-0.3.7/tests/test_beam_judge.py +92 -0
  6. virtual_context-0.3.7/tests/test_conversation_coverage_report.py +145 -0
  7. {virtual_context-0.3.5 → virtual_context-0.3.7}/tests/test_engine_state.py +3 -0
  8. {virtual_context-0.3.5 → virtual_context-0.3.7}/tests/test_engine_sync_turns.py +5 -5
  9. {virtual_context-0.3.5 → virtual_context-0.3.7}/tests/test_fact_redesign.py +62 -4
  10. virtual_context-0.3.7/tests/test_find_quote.py +2207 -0
  11. virtual_context-0.3.7/tests/test_full_text_backfill.py +478 -0
  12. {virtual_context-0.3.5 → virtual_context-0.3.7}/tests/test_passthrough_filter.py +64 -1
  13. {virtual_context-0.3.5 → virtual_context-0.3.7}/tests/test_proxy.py +41 -0
  14. {virtual_context-0.3.5 → virtual_context-0.3.7}/tests/test_proxy_formats.py +153 -0
  15. {virtual_context-0.3.5 → virtual_context-0.3.7}/tests/test_proxy_session.py +55 -0
  16. {virtual_context-0.3.5 → virtual_context-0.3.7}/tests/test_request_captures_persistence.py +122 -0
  17. {virtual_context-0.3.5 → virtual_context-0.3.7}/tests/test_retriever.py +7 -0
  18. {virtual_context-0.3.5 → virtual_context-0.3.7}/tests/test_semantic_search.py +51 -28
  19. {virtual_context-0.3.5 → virtual_context-0.3.7}/tests/test_storage_protocols.py +1 -0
  20. {virtual_context-0.3.5 → virtual_context-0.3.7}/tests/test_store_sqlite.py +33 -0
  21. {virtual_context-0.3.5 → virtual_context-0.3.7}/tests/test_tag_generator.py +59 -0
  22. virtual_context-0.3.7/tests/test_temporal_resolver.py +1352 -0
  23. {virtual_context-0.3.5 → virtual_context-0.3.7}/tests/test_tool_loop.py +389 -5
  24. virtual_context-0.3.7/tests/test_vcattach.py +264 -0
  25. {virtual_context-0.3.5 → virtual_context-0.3.7}/virtual_context/__init__.py +1 -1
  26. {virtual_context-0.3.5 → virtual_context-0.3.7}/virtual_context/core/assembler.py +7 -0
  27. {virtual_context-0.3.5 → virtual_context-0.3.7}/virtual_context/core/compaction_pipeline.py +63 -3
  28. {virtual_context-0.3.5 → virtual_context-0.3.7}/virtual_context/core/compactor.py +210 -15
  29. {virtual_context-0.3.5 → virtual_context-0.3.7}/virtual_context/core/composite_store.py +120 -7
  30. {virtual_context-0.3.5 → virtual_context-0.3.7}/virtual_context/core/conversation_store.py +4 -0
  31. virtual_context-0.3.7/virtual_context/core/coverage_report.py +110 -0
  32. virtual_context-0.3.7/virtual_context/core/full_text_backfill.py +691 -0
  33. {virtual_context-0.3.5 → virtual_context-0.3.7}/virtual_context/core/hint_builder.py +31 -6
  34. virtual_context-0.3.7/virtual_context/core/llm_utils.py +145 -0
  35. {virtual_context-0.3.5 → virtual_context-0.3.7}/virtual_context/core/protocols.py +62 -0
  36. virtual_context-0.3.7/virtual_context/core/quote_search.py +3058 -0
  37. {virtual_context-0.3.5 → virtual_context-0.3.7}/virtual_context/core/retriever.py +2 -0
  38. {virtual_context-0.3.5 → virtual_context-0.3.7}/virtual_context/core/search_engine.py +30 -6
  39. {virtual_context-0.3.5 → virtual_context-0.3.7}/virtual_context/core/segmenter.py +46 -38
  40. {virtual_context-0.3.5 → virtual_context-0.3.7}/virtual_context/core/semantic_search.py +206 -1
  41. {virtual_context-0.3.5 → virtual_context-0.3.7}/virtual_context/core/store.py +87 -5
  42. {virtual_context-0.3.5 → virtual_context-0.3.7}/virtual_context/core/tag_generator.py +119 -8
  43. {virtual_context-0.3.5 → virtual_context-0.3.7}/virtual_context/core/tagging_pipeline.py +53 -20
  44. virtual_context-0.3.7/virtual_context/core/temporal_resolver.py +2447 -0
  45. {virtual_context-0.3.5 → virtual_context-0.3.7}/virtual_context/core/tool_loop.py +367 -31
  46. {virtual_context-0.3.5 → virtual_context-0.3.7}/virtual_context/engine.py +80 -11
  47. {virtual_context-0.3.5 → virtual_context-0.3.7}/virtual_context/mcp/server.py +30 -16
  48. {virtual_context-0.3.5 → virtual_context-0.3.7}/virtual_context/proxy/formats.py +242 -159
  49. {virtual_context-0.3.5 → virtual_context-0.3.7}/virtual_context/proxy/handlers.py +29 -38
  50. {virtual_context-0.3.5 → virtual_context-0.3.7}/virtual_context/proxy/metrics.py +188 -21
  51. {virtual_context-0.3.5 → virtual_context-0.3.7}/virtual_context/proxy/registry.py +27 -1
  52. {virtual_context-0.3.5 → virtual_context-0.3.7}/virtual_context/proxy/server.py +25 -2
  53. {virtual_context-0.3.5 → virtual_context-0.3.7}/virtual_context/proxy/session_state.py +2 -0
  54. {virtual_context-0.3.5 → virtual_context-0.3.7}/virtual_context/proxy/state.py +53 -11
  55. {virtual_context-0.3.5 → virtual_context-0.3.7}/virtual_context/storage/filesystem.py +49 -7
  56. {virtual_context-0.3.5 → virtual_context-0.3.7}/virtual_context/storage/postgres.py +619 -44
  57. {virtual_context-0.3.5 → virtual_context-0.3.7}/virtual_context/storage/sqlite.py +797 -48
  58. {virtual_context-0.3.5 → virtual_context-0.3.7}/virtual_context/types.py +79 -1
  59. virtual_context-0.3.5/README-draft.md +0 -532
  60. virtual_context-0.3.5/README.md.backup +0 -1130
  61. virtual_context-0.3.5/tests/test_find_quote.py +0 -934
  62. virtual_context-0.3.5/tests/test_vcattach.py +0 -121
  63. virtual_context-0.3.5/virtual_context/core/llm_utils.py +0 -65
  64. virtual_context-0.3.5/virtual_context/core/quote_search.py +0 -579
  65. virtual_context-0.3.5/virtual_context/core/temporal_resolver.py +0 -212
  66. {virtual_context-0.3.5 → virtual_context-0.3.7}/.gitignore +0 -0
  67. {virtual_context-0.3.5 → virtual_context-0.3.7}/CLAUDE.md +0 -0
  68. {virtual_context-0.3.5 → virtual_context-0.3.7}/LICENSE +0 -0
  69. {virtual_context-0.3.5 → virtual_context-0.3.7}/README.md +0 -0
  70. {virtual_context-0.3.5 → virtual_context-0.3.7}/assets/dashboard.png +0 -0
  71. {virtual_context-0.3.5 → virtual_context-0.3.7}/assets/hero.png +0 -0
  72. {virtual_context-0.3.5 → virtual_context-0.3.7}/models.yaml +0 -0
  73. {virtual_context-0.3.5 → virtual_context-0.3.7}/scripts/install.ps1 +0 -0
  74. {virtual_context-0.3.5 → virtual_context-0.3.7}/scripts/install.sh +0 -0
  75. {virtual_context-0.3.5 → virtual_context-0.3.7}/specs/cache-aware-compaction.md +0 -0
  76. {virtual_context-0.3.5 → virtual_context-0.3.7}/tests/REGRESSION_MAP.md +0 -0
  77. {virtual_context-0.3.5 → virtual_context-0.3.7}/tests/conftest.py +0 -0
  78. {virtual_context-0.3.5 → virtual_context-0.3.7}/tests/docker-compose.test.yml +0 -0
  79. {virtual_context-0.3.5 → virtual_context-0.3.7}/tests/haiku/__init__.py +0 -0
  80. {virtual_context-0.3.5 → virtual_context-0.3.7}/tests/haiku/conftest.py +0 -0
  81. {virtual_context-0.3.5 → virtual_context-0.3.7}/tests/haiku/test_compaction.py +0 -0
  82. {virtual_context-0.3.5 → virtual_context-0.3.7}/tests/haiku/test_retrieval.py +0 -0
  83. {virtual_context-0.3.5 → virtual_context-0.3.7}/tests/haiku/test_tagging.py +0 -0
  84. {virtual_context-0.3.5 → virtual_context-0.3.7}/tests/ollama/__init__.py +0 -0
  85. {virtual_context-0.3.5 → virtual_context-0.3.7}/tests/ollama/conftest.py +0 -0
  86. {virtual_context-0.3.5 → virtual_context-0.3.7}/tests/ollama/test_compactor.py +0 -0
  87. {virtual_context-0.3.5 → virtual_context-0.3.7}/tests/ollama/test_pipeline.py +0 -0
  88. {virtual_context-0.3.5 → virtual_context-0.3.7}/tests/ollama/test_provider.py +0 -0
  89. {virtual_context-0.3.5 → virtual_context-0.3.7}/tests/ollama/test_tag_generator.py +0 -0
  90. {virtual_context-0.3.5 → virtual_context-0.3.7}/tests/proxy/__init__.py +0 -0
  91. {virtual_context-0.3.5 → virtual_context-0.3.7}/tests/proxy/test_dashboard_cors.py +0 -0
  92. {virtual_context-0.3.5 → virtual_context-0.3.7}/tests/proxy/test_metrics.py +0 -0
  93. {virtual_context-0.3.5 → virtual_context-0.3.7}/tests/test_backend_integration.py +0 -0
  94. {virtual_context-0.3.5 → virtual_context-0.3.7}/tests/test_budget_enforcement.py +0 -0
  95. {virtual_context-0.3.5 → virtual_context-0.3.7}/tests/test_cli_init.py +0 -0
  96. {virtual_context-0.3.5 → virtual_context-0.3.7}/tests/test_compaction_commit_prune.py +0 -0
  97. {virtual_context-0.3.5 → virtual_context-0.3.7}/tests/test_compactor.py +0 -0
  98. {virtual_context-0.3.5 → virtual_context-0.3.7}/tests/test_compactor_concurrent.py +0 -0
  99. {virtual_context-0.3.5 → virtual_context-0.3.7}/tests/test_composite_store.py +0 -0
  100. {virtual_context-0.3.5 → virtual_context-0.3.7}/tests/test_config.py +0 -0
  101. {virtual_context-0.3.5 → virtual_context-0.3.7}/tests/test_context_bleed.py +0 -0
  102. {virtual_context-0.3.5 → virtual_context-0.3.7}/tests/test_conversation_identity.py +0 -0
  103. {virtual_context-0.3.5 → virtual_context-0.3.7}/tests/test_conversation_lifecycle.py +0 -0
  104. {virtual_context-0.3.5 → virtual_context-0.3.7}/tests/test_conversation_scoping.py +0 -0
  105. {virtual_context-0.3.5 → virtual_context-0.3.7}/tests/test_deferred_payload_compaction.py +0 -0
  106. {virtual_context-0.3.5 → virtual_context-0.3.7}/tests/test_embedding_tag_generator.py +0 -0
  107. {virtual_context-0.3.5 → virtual_context-0.3.7}/tests/test_empty_turn_skip.py +0 -0
  108. {virtual_context-0.3.5 → virtual_context-0.3.7}/tests/test_engine_integration.py +0 -0
  109. {virtual_context-0.3.5 → virtual_context-0.3.7}/tests/test_engine_lookback.py +0 -0
  110. {virtual_context-0.3.5 → virtual_context-0.3.7}/tests/test_fact_enrichment.py +0 -0
  111. {virtual_context-0.3.5 → virtual_context-0.3.7}/tests/test_fact_graph_integration.py +0 -0
  112. {virtual_context-0.3.5 → virtual_context-0.3.7}/tests/test_fact_link_checker.py +0 -0
  113. {virtual_context-0.3.5 → virtual_context-0.3.7}/tests/test_fact_link_query.py +0 -0
  114. {virtual_context-0.3.5 → virtual_context-0.3.7}/tests/test_fact_link_types.py +0 -0
  115. {virtual_context-0.3.5 → virtual_context-0.3.7}/tests/test_fact_links_sqlite.py +0 -0
  116. {virtual_context-0.3.5 → virtual_context-0.3.7}/tests/test_fill_pass.py +0 -0
  117. {virtual_context-0.3.5 → virtual_context-0.3.7}/tests/test_format_agnostic.py +0 -0
  118. {virtual_context-0.3.5 → virtual_context-0.3.7}/tests/test_headless.py +0 -0
  119. {virtual_context-0.3.5 → virtual_context-0.3.7}/tests/test_history_filter.py +0 -0
  120. {virtual_context-0.3.5 → virtual_context-0.3.7}/tests/test_idf_retrieval.py +0 -0
  121. {virtual_context-0.3.5 → virtual_context-0.3.7}/tests/test_ingest_index_integrity.py +0 -0
  122. {virtual_context-0.3.5 → virtual_context-0.3.7}/tests/test_longmemeval_auth.py +0 -0
  123. {virtual_context-0.3.5 → virtual_context-0.3.7}/tests/test_mcp_server.py +0 -0
  124. {virtual_context-0.3.5 → virtual_context-0.3.7}/tests/test_media.py +0 -0
  125. {virtual_context-0.3.5 → virtual_context-0.3.7}/tests/test_message_filter.py +0 -0
  126. {virtual_context-0.3.5 → virtual_context-0.3.7}/tests/test_metrics_persistence.py +0 -0
  127. {virtual_context-0.3.5 → virtual_context-0.3.7}/tests/test_model_catalog.py +0 -0
  128. {virtual_context-0.3.5 → virtual_context-0.3.7}/tests/test_model_limits.py +0 -0
  129. {virtual_context-0.3.5 → virtual_context-0.3.7}/tests/test_monitor.py +0 -0
  130. {virtual_context-0.3.5 → virtual_context-0.3.7}/tests/test_multi_instance.py +0 -0
  131. {virtual_context-0.3.5 → virtual_context-0.3.7}/tests/test_noop_fact_link_store.py +0 -0
  132. {virtual_context-0.3.5 → virtual_context-0.3.7}/tests/test_openrouter_provider.py +0 -0
  133. {virtual_context-0.3.5 → virtual_context-0.3.7}/tests/test_paging.py +0 -0
  134. {virtual_context-0.3.5 → virtual_context-0.3.7}/tests/test_presets.py +0 -0
  135. {virtual_context-0.3.5 → virtual_context-0.3.7}/tests/test_prev_context_leak.py +0 -0
  136. {virtual_context-0.3.5 → virtual_context-0.3.7}/tests/test_provider_adapters.py +0 -0
  137. {virtual_context-0.3.5 → virtual_context-0.3.7}/tests/test_proxy_dashboard.py +0 -0
  138. {virtual_context-0.3.5 → virtual_context-0.3.7}/tests/test_proxy_message_filter.py +0 -0
  139. {virtual_context-0.3.5 → virtual_context-0.3.7}/tests/test_proxy_streaming.py +0 -0
  140. {virtual_context-0.3.5 → virtual_context-0.3.7}/tests/test_raw_content.py +0 -0
  141. {virtual_context-0.3.5 → virtual_context-0.3.7}/tests/test_recall_all.py +0 -0
  142. {virtual_context-0.3.5 → virtual_context-0.3.7}/tests/test_registry_lifecycle.py +0 -0
  143. {virtual_context-0.3.5 → virtual_context-0.3.7}/tests/test_rrf_scoring.py +0 -0
  144. {virtual_context-0.3.5 → virtual_context-0.3.7}/tests/test_segmenter.py +0 -0
  145. {virtual_context-0.3.5 → virtual_context-0.3.7}/tests/test_sender_identity.py +0 -0
  146. {virtual_context-0.3.5 → virtual_context-0.3.7}/tests/test_session_cache.py +0 -0
  147. {virtual_context-0.3.5 → virtual_context-0.3.7}/tests/test_session_date.py +0 -0
  148. {virtual_context-0.3.5 → virtual_context-0.3.7}/tests/test_session_state.py +0 -0
  149. {virtual_context-0.3.5 → virtual_context-0.3.7}/tests/test_store_recovery.py +0 -0
  150. {virtual_context-0.3.5 → virtual_context-0.3.7}/tests/test_stub_turn_handling.py +0 -0
  151. {virtual_context-0.3.5 → virtual_context-0.3.7}/tests/test_supersession.py +0 -0
  152. {virtual_context-0.3.5 → virtual_context-0.3.7}/tests/test_supersession_migration.py +0 -0
  153. {virtual_context-0.3.5 → virtual_context-0.3.7}/tests/test_tag_canonicalizer.py +0 -0
  154. {virtual_context-0.3.5 → virtual_context-0.3.7}/tests/test_tag_consolidator.py +0 -0
  155. {virtual_context-0.3.5 → virtual_context-0.3.7}/tests/test_tag_splitter.py +0 -0
  156. {virtual_context-0.3.5 → virtual_context-0.3.7}/tests/test_telemetry.py +0 -0
  157. {virtual_context-0.3.5 → virtual_context-0.3.7}/tests/test_telemetry_integration.py +0 -0
  158. {virtual_context-0.3.5 → virtual_context-0.3.7}/tests/test_tool_output_interceptor.py +0 -0
  159. {virtual_context-0.3.5 → virtual_context-0.3.7}/tests/test_tool_result_filter.py +0 -0
  160. {virtual_context-0.3.5 → virtual_context-0.3.7}/tests/test_tool_tags.py +0 -0
  161. {virtual_context-0.3.5 → virtual_context-0.3.7}/tests/test_tui.py +0 -0
  162. {virtual_context-0.3.5 → virtual_context-0.3.7}/tests/test_turn_grouping.py +0 -0
  163. {virtual_context-0.3.5 → virtual_context-0.3.7}/tests/test_turn_tag_index.py +0 -0
  164. {virtual_context-0.3.5 → virtual_context-0.3.7}/tests/test_unified_budget.py +0 -0
  165. {virtual_context-0.3.5 → virtual_context-0.3.7}/tests/test_upstream_trim.py +0 -0
  166. {virtual_context-0.3.5 → virtual_context-0.3.7}/tests/test_verb_expansion.py +0 -0
  167. {virtual_context-0.3.5 → virtual_context-0.3.7}/virtual-context.yaml +0 -0
  168. {virtual_context-0.3.5 → virtual_context-0.3.7}/virtual-context.yaml.example +0 -0
  169. {virtual_context-0.3.5 → virtual_context-0.3.7}/virtual_context/cli/__init__.py +0 -0
  170. {virtual_context-0.3.5 → virtual_context-0.3.7}/virtual_context/cli/main.py +0 -0
  171. {virtual_context-0.3.5 → virtual_context-0.3.7}/virtual_context/config.py +0 -0
  172. {virtual_context-0.3.5 → virtual_context-0.3.7}/virtual_context/conversation_identity.py +0 -0
  173. {virtual_context-0.3.5 → virtual_context-0.3.7}/virtual_context/core/__init__.py +0 -0
  174. {virtual_context-0.3.5 → virtual_context-0.3.7}/virtual_context/core/embedding_provider.py +0 -0
  175. {virtual_context-0.3.5 → virtual_context-0.3.7}/virtual_context/core/embedding_tag_generator.py +0 -0
  176. {virtual_context-0.3.5 → virtual_context-0.3.7}/virtual_context/core/engine_utils.py +0 -0
  177. {virtual_context-0.3.5 → virtual_context-0.3.7}/virtual_context/core/fact_query.py +0 -0
  178. {virtual_context-0.3.5 → virtual_context-0.3.7}/virtual_context/core/fts_preprocessor.py +0 -0
  179. {virtual_context-0.3.5 → virtual_context-0.3.7}/virtual_context/core/math_utils.py +0 -0
  180. {virtual_context-0.3.5 → virtual_context-0.3.7}/virtual_context/core/model_catalog.py +0 -0
  181. {virtual_context-0.3.5 → virtual_context-0.3.7}/virtual_context/core/monitor.py +0 -0
  182. {virtual_context-0.3.5 → virtual_context-0.3.7}/virtual_context/core/paging_manager.py +0 -0
  183. {virtual_context-0.3.5 → virtual_context-0.3.7}/virtual_context/core/provider_adapters.py +0 -0
  184. {virtual_context-0.3.5 → virtual_context-0.3.7}/virtual_context/core/retrieval_assembler.py +0 -0
  185. {virtual_context-0.3.5 → virtual_context-0.3.7}/virtual_context/core/retrieval_scoring.py +0 -0
  186. {virtual_context-0.3.5 → virtual_context-0.3.7}/virtual_context/core/tag_canonicalizer.py +0 -0
  187. {virtual_context-0.3.5 → virtual_context-0.3.7}/virtual_context/core/tag_consolidator.py +0 -0
  188. {virtual_context-0.3.5 → virtual_context-0.3.7}/virtual_context/core/tag_scoring.py +0 -0
  189. {virtual_context-0.3.5 → virtual_context-0.3.7}/virtual_context/core/tag_splitter.py +0 -0
  190. {virtual_context-0.3.5 → virtual_context-0.3.7}/virtual_context/core/telemetry.py +0 -0
  191. {virtual_context-0.3.5 → virtual_context-0.3.7}/virtual_context/core/tool_query.py +0 -0
  192. {virtual_context-0.3.5 → virtual_context-0.3.7}/virtual_context/core/turn_tag_index.py +0 -0
  193. {virtual_context-0.3.5 → virtual_context-0.3.7}/virtual_context/data/anthropic-tokenizer/tokenizer.json +0 -0
  194. {virtual_context-0.3.5 → virtual_context-0.3.7}/virtual_context/data/models.yaml +0 -0
  195. {virtual_context-0.3.5 → virtual_context-0.3.7}/virtual_context/ingest/__init__.py +0 -0
  196. {virtual_context-0.3.5 → virtual_context-0.3.7}/virtual_context/ingest/curator.py +0 -0
  197. {virtual_context-0.3.5 → virtual_context-0.3.7}/virtual_context/ingest/date_resolver.py +0 -0
  198. {virtual_context-0.3.5 → virtual_context-0.3.7}/virtual_context/ingest/parsers.py +0 -0
  199. {virtual_context-0.3.5 → virtual_context-0.3.7}/virtual_context/ingest/supersession.py +0 -0
  200. {virtual_context-0.3.5 → virtual_context-0.3.7}/virtual_context/mcp/__init__.py +0 -0
  201. {virtual_context-0.3.5 → virtual_context-0.3.7}/virtual_context/model_limits.py +0 -0
  202. {virtual_context-0.3.5 → virtual_context-0.3.7}/virtual_context/openclaw/virtual-context.mjs +0 -0
  203. {virtual_context-0.3.5 → virtual_context-0.3.7}/virtual_context/patterns.py +0 -0
  204. {virtual_context-0.3.5 → virtual_context-0.3.7}/virtual_context/presets/__init__.py +0 -0
  205. {virtual_context-0.3.5 → virtual_context-0.3.7}/virtual_context/presets/agentic.py +0 -0
  206. {virtual_context-0.3.5 → virtual_context-0.3.7}/virtual_context/presets/base.py +0 -0
  207. {virtual_context-0.3.5 → virtual_context-0.3.7}/virtual_context/presets/coding.py +0 -0
  208. {virtual_context-0.3.5 → virtual_context-0.3.7}/virtual_context/providers/__init__.py +0 -0
  209. {virtual_context-0.3.5 → virtual_context-0.3.7}/virtual_context/providers/anthropic.py +0 -0
  210. {virtual_context-0.3.5 → virtual_context-0.3.7}/virtual_context/providers/base.py +0 -0
  211. {virtual_context-0.3.5 → virtual_context-0.3.7}/virtual_context/providers/generic_openai.py +0 -0
  212. {virtual_context-0.3.5 → virtual_context-0.3.7}/virtual_context/providers/ollama_native.py +0 -0
  213. {virtual_context-0.3.5 → virtual_context-0.3.7}/virtual_context/proxy/__init__.py +0 -0
  214. {virtual_context-0.3.5 → virtual_context-0.3.7}/virtual_context/proxy/_envelope.py +0 -0
  215. {virtual_context-0.3.5 → virtual_context-0.3.7}/virtual_context/proxy/dashboard.html +0 -0
  216. {virtual_context-0.3.5 → virtual_context-0.3.7}/virtual_context/proxy/dashboard.py +0 -0
  217. {virtual_context-0.3.5 → virtual_context-0.3.7}/virtual_context/proxy/helpers.py +0 -0
  218. {virtual_context-0.3.5 → virtual_context-0.3.7}/virtual_context/proxy/media.py +0 -0
  219. {virtual_context-0.3.5 → virtual_context-0.3.7}/virtual_context/proxy/message_filter.py +0 -0
  220. {virtual_context-0.3.5 → virtual_context-0.3.7}/virtual_context/proxy/multi.py +0 -0
  221. {virtual_context-0.3.5 → virtual_context-0.3.7}/virtual_context/proxy/session_cache.py +0 -0
  222. {virtual_context-0.3.5 → virtual_context-0.3.7}/virtual_context/proxy/static/android-chrome-192x192.png +0 -0
  223. {virtual_context-0.3.5 → virtual_context-0.3.7}/virtual_context/proxy/static/android-chrome-512x512.png +0 -0
  224. {virtual_context-0.3.5 → virtual_context-0.3.7}/virtual_context/proxy/static/apple-touch-icon.png +0 -0
  225. {virtual_context-0.3.5 → virtual_context-0.3.7}/virtual_context/proxy/static/favicon-16x16.png +0 -0
  226. {virtual_context-0.3.5 → virtual_context-0.3.7}/virtual_context/proxy/static/favicon-32x32.png +0 -0
  227. {virtual_context-0.3.5 → virtual_context-0.3.7}/virtual_context/proxy/static/favicon.ico +0 -0
  228. {virtual_context-0.3.5 → virtual_context-0.3.7}/virtual_context/proxy/static/site.webmanifest +0 -0
  229. {virtual_context-0.3.5 → virtual_context-0.3.7}/virtual_context/proxy/tool_output_interceptor.py +0 -0
  230. {virtual_context-0.3.5 → virtual_context-0.3.7}/virtual_context/proxy/vcattach.py +0 -0
  231. {virtual_context-0.3.5 → virtual_context-0.3.7}/virtual_context/storage/__init__.py +0 -0
  232. {virtual_context-0.3.5 → virtual_context-0.3.7}/virtual_context/storage/falkordb.py +0 -0
  233. {virtual_context-0.3.5 → virtual_context-0.3.7}/virtual_context/storage/helpers.py +0 -0
  234. {virtual_context-0.3.5 → virtual_context-0.3.7}/virtual_context/storage/neo4j.py +0 -0
  235. {virtual_context-0.3.5 → virtual_context-0.3.7}/virtual_context/storage/noop_fact_link_store.py +0 -0
  236. {virtual_context-0.3.5 → virtual_context-0.3.7}/virtual_context/token_counter.py +0 -0
  237. {virtual_context-0.3.5 → virtual_context-0.3.7}/virtual_context/tui/__init__.py +0 -0
  238. {virtual_context-0.3.5 → virtual_context-0.3.7}/virtual_context/tui/app.py +0 -0
  239. {virtual_context-0.3.5 → virtual_context-0.3.7}/virtual_context/tui/chat.tcss +0 -0
  240. {virtual_context-0.3.5 → virtual_context-0.3.7}/virtual_context/tui/chat_provider.py +0 -0
  241. {virtual_context-0.3.5 → virtual_context-0.3.7}/virtual_context/tui/headless.py +0 -0
  242. {virtual_context-0.3.5 → virtual_context-0.3.7}/virtual_context/tui/modals/__init__.py +0 -0
  243. {virtual_context-0.3.5 → virtual_context-0.3.7}/virtual_context/tui/modals/turn_inspector.py +0 -0
  244. {virtual_context-0.3.5 → virtual_context-0.3.7}/virtual_context/tui/state.py +0 -0
  245. {virtual_context-0.3.5 → virtual_context-0.3.7}/virtual_context/tui/widgets/__init__.py +0 -0
  246. {virtual_context-0.3.5 → virtual_context-0.3.7}/virtual_context/tui/widgets/budget_bar.py +0 -0
  247. {virtual_context-0.3.5 → virtual_context-0.3.7}/virtual_context/tui/widgets/chat_view.py +0 -0
  248. {virtual_context-0.3.5 → virtual_context-0.3.7}/virtual_context/tui/widgets/input_box.py +0 -0
  249. {virtual_context-0.3.5 → virtual_context-0.3.7}/virtual_context/tui/widgets/tag_panel.py +0 -0
  250. {virtual_context-0.3.5 → virtual_context-0.3.7}/virtual_context/tui/widgets/turn_list.py +0 -0
@@ -6,10 +6,14 @@ on:
6
6
 
7
7
  permissions:
8
8
  contents: read
9
+ id-token: write
9
10
 
10
11
  jobs:
11
12
  publish:
12
13
  runs-on: ubuntu-latest
14
+ environment:
15
+ name: pypi
16
+ url: https://pypi.org/p/virtual-context
13
17
 
14
18
  steps:
15
19
  - uses: actions/checkout@v4
@@ -25,5 +29,3 @@ jobs:
25
29
 
26
30
  - name: Publish to PyPI
27
31
  uses: pypa/gh-action-pypi-publish@release/v1
28
- with:
29
- password: ${{ secrets.PYPI_API_TOKEN }}
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: virtual-context
3
- Version: 0.3.5
3
+ Version: 0.3.7
4
4
  Summary: OS-style virtual memory for LLM session context management
5
5
  Project-URL: Homepage, https://virtual-context.com
6
6
  Project-URL: Repository, https://github.com/virtual-context/virtual-context
@@ -4,7 +4,7 @@ build-backend = "hatchling.build"
4
4
 
5
5
  [project]
6
6
  name = "virtual-context"
7
- version = "0.3.5"
7
+ version = "0.3.7"
8
8
  description = "OS-style virtual memory for LLM session context management"
9
9
  readme = "README.md"
10
10
  license = "AGPL-3.0-or-later"
@@ -4,7 +4,7 @@ from datetime import datetime, timezone
4
4
 
5
5
  import pytest
6
6
 
7
- from virtual_context.core.assembler import ContextAssembler
7
+ from virtual_context.core.assembler import ContextAssembler, format_tag_section
8
8
  from virtual_context.types import (
9
9
  AssemblerConfig,
10
10
  Message,
@@ -77,6 +77,36 @@ def test_assemble_xml_tags(assembler, retrieval_result):
77
77
  assert "</virtual-context>" in section
78
78
 
79
79
 
80
+ def test_format_tag_section_renders_code_refs():
81
+ now = datetime.now(timezone.utc)
82
+ section = format_tag_section(
83
+ "backend",
84
+ [
85
+ StoredSummary(
86
+ ref="ref-1",
87
+ primary_tag="backend",
88
+ tags=["backend"],
89
+ summary="Request cache boundary moved ahead of the mutable reminder.",
90
+ summary_tokens=18,
91
+ full_tokens=50,
92
+ metadata=SegmentMetadata(
93
+ code_refs=[
94
+ {"file": "virtual_context/proxy/formats.py", "line": 1312, "symbol": "inject_context"},
95
+ {"file": "virtual_context/core/provider_adapters.py", "symbol": "AnthropicAdapter"},
96
+ ],
97
+ ),
98
+ created_at=now,
99
+ start_timestamp=now,
100
+ end_timestamp=now,
101
+ ),
102
+ ],
103
+ )
104
+
105
+ assert "[refs:" in section
106
+ assert "virtual_context/proxy/formats.py:1312 inject_context" in section
107
+ assert "virtual_context/core/provider_adapters.py AnthropicAdapter" in section
108
+
109
+
80
110
  def test_trim_conversation(assembler):
81
111
  messages = [
82
112
  Message(role="user", content="x" * 400),
@@ -0,0 +1,92 @@
1
+ from __future__ import annotations
2
+
3
+ from benchmarks.beam.dataset import BEAMQuestion
4
+ from benchmarks.beam.judge import judge_answer
5
+ from benchmarks.beam.run_beam import _parse_args
6
+
7
+
8
+ def _event_ordering_question() -> BEAMQuestion:
9
+ return BEAMQuestion(
10
+ question_id="10M_1_event_ordering_0",
11
+ question="Reconstruct the ordered sequence of milestones.",
12
+ category="event_ordering",
13
+ rubric=[
14
+ "token limits and segmentation",
15
+ "reranking and feedback parsing",
16
+ "language detection and vector alignment",
17
+ ],
18
+ ideal_response="",
19
+ difficulty="medium",
20
+ )
21
+
22
+
23
+ def test_fast_event_ordering_judge_matches_paraphrases_without_llm(monkeypatch) -> None:
24
+ def _should_not_call(*args, **kwargs):
25
+ raise AssertionError("fast event ordering judge should not call the judge LLM")
26
+
27
+ monkeypatch.setattr("benchmarks.beam.judge._call_judge_llm", _should_not_call)
28
+
29
+ result = judge_answer(
30
+ _event_ordering_question(),
31
+ "\n".join([
32
+ "segmentation and token limit handling",
33
+ "feedback parsing plus reranking problems",
34
+ "vector alignment with language detection",
35
+ ]),
36
+ event_ordering_mode="fast",
37
+ )
38
+
39
+ assert result["method"] == "kendall_tau_fast"
40
+ assert result["score"] == 1.0
41
+ assert len(result["criteria_met"]) == 3
42
+
43
+
44
+ def test_fast_event_ordering_judge_penalizes_wrong_order(monkeypatch) -> None:
45
+ def _should_not_call(*args, **kwargs):
46
+ raise AssertionError("fast event ordering judge should not call the judge LLM")
47
+
48
+ monkeypatch.setattr("benchmarks.beam.judge._call_judge_llm", _should_not_call)
49
+
50
+ result = judge_answer(
51
+ _event_ordering_question(),
52
+ "\n".join([
53
+ "vector alignment with language detection",
54
+ "feedback parsing plus reranking problems",
55
+ "segmentation and token limit handling",
56
+ ]),
57
+ event_ordering_mode="fast",
58
+ )
59
+
60
+ assert result["method"] == "kendall_tau_fast"
61
+ assert result["score"] < 1.0
62
+ assert result["tau_norm"] < 1.0
63
+
64
+
65
+ def test_run_beam_parse_args_accepts_fast_event_ordering_mode() -> None:
66
+ args = _parse_args([
67
+ "--chat-size", "10M",
68
+ "--tagger-model", "claude-haiku-4-5-20251001",
69
+ "--event-ordering-judge-mode", "fast",
70
+ ])
71
+ assert args.event_ordering_judge_mode == "fast"
72
+
73
+
74
+ def test_fast_event_ordering_judge_returns_zero_not_nan_for_no_matches(monkeypatch) -> None:
75
+ def _should_not_call(*args, **kwargs):
76
+ raise AssertionError("fast event ordering judge should not call the judge LLM")
77
+
78
+ monkeypatch.setattr("benchmarks.beam.judge._call_judge_llm", _should_not_call)
79
+
80
+ result = judge_answer(
81
+ _event_ordering_question(),
82
+ "\n".join([
83
+ "completely unrelated infrastructure planning",
84
+ "team retro and onboarding notes",
85
+ ]),
86
+ event_ordering_mode="fast",
87
+ )
88
+
89
+ assert result["method"] == "kendall_tau_fast"
90
+ assert isinstance(float(result["score"]), float)
91
+ assert result["score"] == result["score"]
92
+ assert result["alignments"] == []
@@ -0,0 +1,145 @@
1
+ from datetime import datetime, timezone
2
+
3
+ from virtual_context.core.coverage_report import build_conversation_coverage_report
4
+ from virtual_context.storage.sqlite import SQLiteStore
5
+ from virtual_context.types import SegmentMetadata, StoredSegment, TagSummary
6
+
7
+
8
+ def _make_segment(
9
+ ref: str,
10
+ *,
11
+ conversation_id: str,
12
+ turn_count: int,
13
+ start_turn_number: int,
14
+ end_turn_number: int,
15
+ generated_by_turn_id: str,
16
+ created_at: datetime,
17
+ ) -> StoredSegment:
18
+ return StoredSegment(
19
+ ref=ref,
20
+ conversation_id=conversation_id,
21
+ primary_tag="topic",
22
+ tags=["topic"],
23
+ summary=f"summary {ref}",
24
+ summary_tokens=10,
25
+ full_text=f"full {ref}",
26
+ full_tokens=20,
27
+ messages=[{"role": "user", "content": ref}],
28
+ metadata=SegmentMetadata(
29
+ turn_count=turn_count,
30
+ start_turn_number=start_turn_number,
31
+ end_turn_number=end_turn_number,
32
+ generated_by_turn_id=generated_by_turn_id,
33
+ ),
34
+ created_at=created_at,
35
+ start_timestamp=created_at,
36
+ end_timestamp=created_at,
37
+ compaction_model="test",
38
+ compression_ratio=0.5,
39
+ )
40
+
41
+
42
+ def test_build_conversation_coverage_report_uses_latest_payload_and_exact_ranges(tmp_path):
43
+ store = SQLiteStore(tmp_path / "test.db")
44
+ conversation_id = "conv-1"
45
+ now = datetime(2026, 4, 10, 12, 0, tzinfo=timezone.utc)
46
+
47
+ store.store_segment(
48
+ _make_segment(
49
+ "seg-a",
50
+ conversation_id=conversation_id,
51
+ turn_count=3,
52
+ start_turn_number=0,
53
+ end_turn_number=2,
54
+ generated_by_turn_id="req-a",
55
+ created_at=now,
56
+ )
57
+ )
58
+ store.store_segment(
59
+ _make_segment(
60
+ "seg-b",
61
+ conversation_id=conversation_id,
62
+ turn_count=3,
63
+ start_turn_number=2,
64
+ end_turn_number=4,
65
+ generated_by_turn_id="req-b",
66
+ created_at=now.replace(hour=13),
67
+ )
68
+ )
69
+ store.store_segment(
70
+ _make_segment(
71
+ "seg-c",
72
+ conversation_id=conversation_id,
73
+ turn_count=4,
74
+ start_turn_number=-1,
75
+ end_turn_number=-1,
76
+ generated_by_turn_id="",
77
+ created_at=now.replace(hour=14),
78
+ )
79
+ )
80
+ store.save_tag_summary(
81
+ TagSummary(
82
+ tag="topic",
83
+ summary="rollup",
84
+ summary_tokens=12,
85
+ covers_through_turn=8,
86
+ generated_by_turn_id="req-b",
87
+ created_at=now.replace(hour=15),
88
+ updated_at=now.replace(hour=15),
89
+ ),
90
+ conversation_id=conversation_id,
91
+ )
92
+ store.save_request_capture(
93
+ {
94
+ "turn": 9,
95
+ "turn_id": "req-latest",
96
+ "ts": "2026-04-10T16:30:00+00:00",
97
+ "api_format": "anthropic",
98
+ "model": "test",
99
+ "stream": False,
100
+ "message_count": 6,
101
+ "client_payload_message_count": 6,
102
+ "client_payload_pair_count": 3,
103
+ "client_payload_user_prompt_count": 3,
104
+ "client_payload_timestamped_message_count": 3,
105
+ "client_payload_earliest_timestamp": "2026-03-15T16:10:00+00:00",
106
+ "client_payload_latest_timestamp": "2026-04-10T16:29:00+00:00",
107
+ "conversation_id": conversation_id,
108
+ "inbound_tags": [],
109
+ "response_tags": [],
110
+ "passthrough": False,
111
+ "inbound_tokens": 0,
112
+ "outbound_tokens": 0,
113
+ "inbound_bytes": 0,
114
+ "outbound_bytes": 0,
115
+ "context_tokens": 0,
116
+ "overhead_ms": 0,
117
+ "turns_dropped": 0,
118
+ "turns_stubbed": 0,
119
+ "message_preview": "",
120
+ "upstream_input_tokens": 0,
121
+ "upstream_output_tokens": 0,
122
+ "cache_creation_input_tokens": 0,
123
+ "cache_read_input_tokens": 0,
124
+ }
125
+ )
126
+
127
+ report = build_conversation_coverage_report(store, conversation_id)
128
+
129
+ assert report.conversation_id == conversation_id
130
+ assert report.latest_payload.turn == 9
131
+ assert report.latest_payload.turn_id == "req-latest"
132
+ assert report.latest_payload.message_count == 6
133
+ assert report.latest_payload.pair_count == 3
134
+ assert report.latest_payload.user_prompt_count == 3
135
+ assert report.latest_payload.timestamped_message_count == 3
136
+ assert report.latest_payload.earliest_timestamp == "2026-03-15T16:10:00+00:00"
137
+ assert report.latest_payload.latest_timestamp == "2026-04-10T16:29:00+00:00"
138
+ assert report.segment_count == 3
139
+ assert report.summarized_turn_occurrences == 10
140
+ assert report.exact_range_segment_count == 2
141
+ assert report.exact_unique_turn_count == 5
142
+ assert report.exact_start_turn_number == 0
143
+ assert report.exact_end_turn_number == 4
144
+ assert report.tag_summary_count == 1
145
+ assert report.max_tag_summary_turn == 8
@@ -28,6 +28,7 @@ def _make_snapshot(
28
28
  tags=[f"tag-{i}", "common"],
29
29
  primary_tag=f"tag-{i}",
30
30
  timestamp=datetime(2026, 1, 15, 10, i, 0, tzinfo=timezone.utc),
31
+ code_refs=[{"file": f"src/module_{i}.py", "line": i + 1, "symbol": f"func_{i}"}],
31
32
  )
32
33
  for i in range(turn_count)
33
34
  ]
@@ -75,6 +76,7 @@ class TestEngineStateSQLite:
75
76
  assert restored.tags == orig.tags
76
77
  assert restored.primary_tag == orig.primary_tag
77
78
  assert restored.timestamp == orig.timestamp
79
+ assert restored.code_refs == orig.code_refs
78
80
 
79
81
  def test_load_empty_store(self, tmp_path):
80
82
  """Loading from an empty store returns None."""
@@ -131,6 +133,7 @@ class TestEngineStateFilesystem:
131
133
  assert restored.message_hash == orig.message_hash
132
134
  assert restored.tags == orig.tags
133
135
  assert restored.primary_tag == orig.primary_tag
136
+ assert restored.code_refs == orig.code_refs
134
137
 
135
138
  def test_load_empty_store(self, tmp_path):
136
139
  """Loading from an empty store returns None."""
@@ -67,16 +67,16 @@ def engine(tmp_path):
67
67
 
68
68
 
69
69
  def _search_via_store(engine, query):
70
- """Search turn_messages through the CompositeStore delegate (Task 1).
70
+ """Search canonical full_text through the CompositeStore delegate.
71
71
 
72
- Validates that the CompositeStore.search_turn_messages delegation works,
72
+ Validates that the CompositeStore.search_canonical_full_text delegation works,
73
73
  not just the raw concrete store method.
74
74
  """
75
75
  store = engine._store
76
- _search = getattr(store, "search_turn_messages", None)
76
+ _search = getattr(store, "search_canonical_full_text", None)
77
77
  assert _search is not None, (
78
- "search_turn_messages not reachable through store chain — "
79
- "CompositeStore delegation missing (Task 1)")
78
+ "search_canonical_full_text not reachable through store chain — "
79
+ "CompositeStore delegation missing")
80
80
  return _search(query, conversation_id="test-conv-sync")
81
81
 
82
82
 
@@ -61,17 +61,75 @@ def test_compaction_uses_replace_facts_for_segment():
61
61
 
62
62
  def test_code_mode_prompt_appended():
63
63
  """When code_mode is True, the compactor prompt should include the code mode block."""
64
- from virtual_context.core.compactor import CODE_MODE_FACT_PROMPT
65
- assert "Do NOT extract intermediary" in CODE_MODE_FACT_PROMPT
66
- assert "conclusions, findings, discoveries" in CODE_MODE_FACT_PROMPT
64
+ from virtual_context.core.compactor import (
65
+ CODE_FACT_EXTRACTION_PROMPT,
66
+ CODE_SUMMARY_PROMPT,
67
+ CODE_TAG_SUMMARY_ROLLUP_PROMPT,
68
+ )
69
+ assert "Do NOT extract intermediary" in CODE_FACT_EXTRACTION_PROMPT
70
+ assert "conclusions, findings, discoveries" in CODE_FACT_EXTRACTION_PROMPT
71
+ assert "engineering conversation segment" in CODE_SUMMARY_PROMPT
72
+ assert '"code_refs"' in CODE_SUMMARY_PROMPT
73
+ assert "rolling up engineering context" in CODE_TAG_SUMMARY_ROLLUP_PROMPT
74
+
75
+
76
+ def test_compactor_template_path_appends_code_fact_prompt():
77
+ from datetime import datetime, timezone
78
+ from unittest.mock import MagicMock
79
+
80
+ from virtual_context.core.compactor import CODE_FACT_EXTRACTION_PROMPT, DomainCompactor
81
+ from virtual_context.types import Message, TaggedSegment
82
+
83
+ captured: dict[str, str] = {}
84
+
85
+ llm = MagicMock()
86
+
87
+ def _complete(*, system, user, max_tokens):
88
+ captured["user"] = user
89
+ return ('{"summary":"ok","entities":[],"key_decisions":[],"action_items":[],"date_references":[],"refined_tags":[],"code_refs":[]}', {})
90
+
91
+ llm.complete.side_effect = _complete
92
+
93
+ compactor = DomainCompactor(
94
+ llm_provider=llm,
95
+ config=CompactorConfig(code_mode=True),
96
+ )
97
+
98
+ seg = TaggedSegment(
99
+ primary_tag="backend",
100
+ tags=["backend"],
101
+ messages=[
102
+ Message(role="user", content="We changed the request cache boundary in formats.py."),
103
+ Message(role="assistant", content="It now sits above the mutable VC injection block."),
104
+ ],
105
+ token_count=40,
106
+ start_timestamp=datetime.now(timezone.utc),
107
+ end_timestamp=datetime.now(timezone.utc),
108
+ turn_count=1,
109
+ )
110
+
111
+ compactor._compact_one(seg)
112
+
113
+ assert CODE_FACT_EXTRACTION_PROMPT.strip() in captured["user"]
67
114
 
68
115
 
69
116
  def test_tag_generator_accepts_code_mode():
70
- from virtual_context.core.tag_generator import LLMTagGenerator
117
+ from virtual_context.core.tag_generator import (
118
+ CODE_TAG_GENERATOR_PROMPT_COMPACT,
119
+ CODE_TAG_GENERATOR_PROMPT_DETAILED,
120
+ CODE_TAG_GENERATOR_PROMPT_SMALL_MODEL,
121
+ LLMTagGenerator,
122
+ )
71
123
  from virtual_context.types import TagGeneratorConfig
72
124
  from unittest.mock import MagicMock
73
125
  gen = LLMTagGenerator(llm_provider=MagicMock(), config=TagGeneratorConfig(), code_mode=True)
74
126
  assert gen._code_mode is True
127
+ assert "engineering and code conversations" in CODE_TAG_GENERATOR_PROMPT_DETAILED
128
+ assert "fact_signals" in CODE_TAG_GENERATOR_PROMPT_DETAILED
129
+ assert "engineering and code conversations" in CODE_TAG_GENERATOR_PROMPT_COMPACT
130
+ assert "fact_signals" in CODE_TAG_GENERATOR_PROMPT_COMPACT
131
+ assert "engineering and code conversations" in CODE_TAG_GENERATOR_PROMPT_SMALL_MODEL
132
+ assert "fact_signals" in CODE_TAG_GENERATOR_PROMPT_SMALL_MODEL
75
133
 
76
134
 
77
135
  def test_build_tag_generator_passes_code_mode():