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.
- {virtual_context-0.3.5 → virtual_context-0.3.7}/.github/workflows/python-publish.yml +4 -2
- {virtual_context-0.3.5 → virtual_context-0.3.7}/PKG-INFO +1 -1
- {virtual_context-0.3.5 → virtual_context-0.3.7}/pyproject.toml +1 -1
- {virtual_context-0.3.5 → virtual_context-0.3.7}/tests/test_assembler.py +31 -1
- virtual_context-0.3.7/tests/test_beam_judge.py +92 -0
- virtual_context-0.3.7/tests/test_conversation_coverage_report.py +145 -0
- {virtual_context-0.3.5 → virtual_context-0.3.7}/tests/test_engine_state.py +3 -0
- {virtual_context-0.3.5 → virtual_context-0.3.7}/tests/test_engine_sync_turns.py +5 -5
- {virtual_context-0.3.5 → virtual_context-0.3.7}/tests/test_fact_redesign.py +62 -4
- virtual_context-0.3.7/tests/test_find_quote.py +2207 -0
- virtual_context-0.3.7/tests/test_full_text_backfill.py +478 -0
- {virtual_context-0.3.5 → virtual_context-0.3.7}/tests/test_passthrough_filter.py +64 -1
- {virtual_context-0.3.5 → virtual_context-0.3.7}/tests/test_proxy.py +41 -0
- {virtual_context-0.3.5 → virtual_context-0.3.7}/tests/test_proxy_formats.py +153 -0
- {virtual_context-0.3.5 → virtual_context-0.3.7}/tests/test_proxy_session.py +55 -0
- {virtual_context-0.3.5 → virtual_context-0.3.7}/tests/test_request_captures_persistence.py +122 -0
- {virtual_context-0.3.5 → virtual_context-0.3.7}/tests/test_retriever.py +7 -0
- {virtual_context-0.3.5 → virtual_context-0.3.7}/tests/test_semantic_search.py +51 -28
- {virtual_context-0.3.5 → virtual_context-0.3.7}/tests/test_storage_protocols.py +1 -0
- {virtual_context-0.3.5 → virtual_context-0.3.7}/tests/test_store_sqlite.py +33 -0
- {virtual_context-0.3.5 → virtual_context-0.3.7}/tests/test_tag_generator.py +59 -0
- virtual_context-0.3.7/tests/test_temporal_resolver.py +1352 -0
- {virtual_context-0.3.5 → virtual_context-0.3.7}/tests/test_tool_loop.py +389 -5
- virtual_context-0.3.7/tests/test_vcattach.py +264 -0
- {virtual_context-0.3.5 → virtual_context-0.3.7}/virtual_context/__init__.py +1 -1
- {virtual_context-0.3.5 → virtual_context-0.3.7}/virtual_context/core/assembler.py +7 -0
- {virtual_context-0.3.5 → virtual_context-0.3.7}/virtual_context/core/compaction_pipeline.py +63 -3
- {virtual_context-0.3.5 → virtual_context-0.3.7}/virtual_context/core/compactor.py +210 -15
- {virtual_context-0.3.5 → virtual_context-0.3.7}/virtual_context/core/composite_store.py +120 -7
- {virtual_context-0.3.5 → virtual_context-0.3.7}/virtual_context/core/conversation_store.py +4 -0
- virtual_context-0.3.7/virtual_context/core/coverage_report.py +110 -0
- virtual_context-0.3.7/virtual_context/core/full_text_backfill.py +691 -0
- {virtual_context-0.3.5 → virtual_context-0.3.7}/virtual_context/core/hint_builder.py +31 -6
- virtual_context-0.3.7/virtual_context/core/llm_utils.py +145 -0
- {virtual_context-0.3.5 → virtual_context-0.3.7}/virtual_context/core/protocols.py +62 -0
- virtual_context-0.3.7/virtual_context/core/quote_search.py +3058 -0
- {virtual_context-0.3.5 → virtual_context-0.3.7}/virtual_context/core/retriever.py +2 -0
- {virtual_context-0.3.5 → virtual_context-0.3.7}/virtual_context/core/search_engine.py +30 -6
- {virtual_context-0.3.5 → virtual_context-0.3.7}/virtual_context/core/segmenter.py +46 -38
- {virtual_context-0.3.5 → virtual_context-0.3.7}/virtual_context/core/semantic_search.py +206 -1
- {virtual_context-0.3.5 → virtual_context-0.3.7}/virtual_context/core/store.py +87 -5
- {virtual_context-0.3.5 → virtual_context-0.3.7}/virtual_context/core/tag_generator.py +119 -8
- {virtual_context-0.3.5 → virtual_context-0.3.7}/virtual_context/core/tagging_pipeline.py +53 -20
- virtual_context-0.3.7/virtual_context/core/temporal_resolver.py +2447 -0
- {virtual_context-0.3.5 → virtual_context-0.3.7}/virtual_context/core/tool_loop.py +367 -31
- {virtual_context-0.3.5 → virtual_context-0.3.7}/virtual_context/engine.py +80 -11
- {virtual_context-0.3.5 → virtual_context-0.3.7}/virtual_context/mcp/server.py +30 -16
- {virtual_context-0.3.5 → virtual_context-0.3.7}/virtual_context/proxy/formats.py +242 -159
- {virtual_context-0.3.5 → virtual_context-0.3.7}/virtual_context/proxy/handlers.py +29 -38
- {virtual_context-0.3.5 → virtual_context-0.3.7}/virtual_context/proxy/metrics.py +188 -21
- {virtual_context-0.3.5 → virtual_context-0.3.7}/virtual_context/proxy/registry.py +27 -1
- {virtual_context-0.3.5 → virtual_context-0.3.7}/virtual_context/proxy/server.py +25 -2
- {virtual_context-0.3.5 → virtual_context-0.3.7}/virtual_context/proxy/session_state.py +2 -0
- {virtual_context-0.3.5 → virtual_context-0.3.7}/virtual_context/proxy/state.py +53 -11
- {virtual_context-0.3.5 → virtual_context-0.3.7}/virtual_context/storage/filesystem.py +49 -7
- {virtual_context-0.3.5 → virtual_context-0.3.7}/virtual_context/storage/postgres.py +619 -44
- {virtual_context-0.3.5 → virtual_context-0.3.7}/virtual_context/storage/sqlite.py +797 -48
- {virtual_context-0.3.5 → virtual_context-0.3.7}/virtual_context/types.py +79 -1
- virtual_context-0.3.5/README-draft.md +0 -532
- virtual_context-0.3.5/README.md.backup +0 -1130
- virtual_context-0.3.5/tests/test_find_quote.py +0 -934
- virtual_context-0.3.5/tests/test_vcattach.py +0 -121
- virtual_context-0.3.5/virtual_context/core/llm_utils.py +0 -65
- virtual_context-0.3.5/virtual_context/core/quote_search.py +0 -579
- virtual_context-0.3.5/virtual_context/core/temporal_resolver.py +0 -212
- {virtual_context-0.3.5 → virtual_context-0.3.7}/.gitignore +0 -0
- {virtual_context-0.3.5 → virtual_context-0.3.7}/CLAUDE.md +0 -0
- {virtual_context-0.3.5 → virtual_context-0.3.7}/LICENSE +0 -0
- {virtual_context-0.3.5 → virtual_context-0.3.7}/README.md +0 -0
- {virtual_context-0.3.5 → virtual_context-0.3.7}/assets/dashboard.png +0 -0
- {virtual_context-0.3.5 → virtual_context-0.3.7}/assets/hero.png +0 -0
- {virtual_context-0.3.5 → virtual_context-0.3.7}/models.yaml +0 -0
- {virtual_context-0.3.5 → virtual_context-0.3.7}/scripts/install.ps1 +0 -0
- {virtual_context-0.3.5 → virtual_context-0.3.7}/scripts/install.sh +0 -0
- {virtual_context-0.3.5 → virtual_context-0.3.7}/specs/cache-aware-compaction.md +0 -0
- {virtual_context-0.3.5 → virtual_context-0.3.7}/tests/REGRESSION_MAP.md +0 -0
- {virtual_context-0.3.5 → virtual_context-0.3.7}/tests/conftest.py +0 -0
- {virtual_context-0.3.5 → virtual_context-0.3.7}/tests/docker-compose.test.yml +0 -0
- {virtual_context-0.3.5 → virtual_context-0.3.7}/tests/haiku/__init__.py +0 -0
- {virtual_context-0.3.5 → virtual_context-0.3.7}/tests/haiku/conftest.py +0 -0
- {virtual_context-0.3.5 → virtual_context-0.3.7}/tests/haiku/test_compaction.py +0 -0
- {virtual_context-0.3.5 → virtual_context-0.3.7}/tests/haiku/test_retrieval.py +0 -0
- {virtual_context-0.3.5 → virtual_context-0.3.7}/tests/haiku/test_tagging.py +0 -0
- {virtual_context-0.3.5 → virtual_context-0.3.7}/tests/ollama/__init__.py +0 -0
- {virtual_context-0.3.5 → virtual_context-0.3.7}/tests/ollama/conftest.py +0 -0
- {virtual_context-0.3.5 → virtual_context-0.3.7}/tests/ollama/test_compactor.py +0 -0
- {virtual_context-0.3.5 → virtual_context-0.3.7}/tests/ollama/test_pipeline.py +0 -0
- {virtual_context-0.3.5 → virtual_context-0.3.7}/tests/ollama/test_provider.py +0 -0
- {virtual_context-0.3.5 → virtual_context-0.3.7}/tests/ollama/test_tag_generator.py +0 -0
- {virtual_context-0.3.5 → virtual_context-0.3.7}/tests/proxy/__init__.py +0 -0
- {virtual_context-0.3.5 → virtual_context-0.3.7}/tests/proxy/test_dashboard_cors.py +0 -0
- {virtual_context-0.3.5 → virtual_context-0.3.7}/tests/proxy/test_metrics.py +0 -0
- {virtual_context-0.3.5 → virtual_context-0.3.7}/tests/test_backend_integration.py +0 -0
- {virtual_context-0.3.5 → virtual_context-0.3.7}/tests/test_budget_enforcement.py +0 -0
- {virtual_context-0.3.5 → virtual_context-0.3.7}/tests/test_cli_init.py +0 -0
- {virtual_context-0.3.5 → virtual_context-0.3.7}/tests/test_compaction_commit_prune.py +0 -0
- {virtual_context-0.3.5 → virtual_context-0.3.7}/tests/test_compactor.py +0 -0
- {virtual_context-0.3.5 → virtual_context-0.3.7}/tests/test_compactor_concurrent.py +0 -0
- {virtual_context-0.3.5 → virtual_context-0.3.7}/tests/test_composite_store.py +0 -0
- {virtual_context-0.3.5 → virtual_context-0.3.7}/tests/test_config.py +0 -0
- {virtual_context-0.3.5 → virtual_context-0.3.7}/tests/test_context_bleed.py +0 -0
- {virtual_context-0.3.5 → virtual_context-0.3.7}/tests/test_conversation_identity.py +0 -0
- {virtual_context-0.3.5 → virtual_context-0.3.7}/tests/test_conversation_lifecycle.py +0 -0
- {virtual_context-0.3.5 → virtual_context-0.3.7}/tests/test_conversation_scoping.py +0 -0
- {virtual_context-0.3.5 → virtual_context-0.3.7}/tests/test_deferred_payload_compaction.py +0 -0
- {virtual_context-0.3.5 → virtual_context-0.3.7}/tests/test_embedding_tag_generator.py +0 -0
- {virtual_context-0.3.5 → virtual_context-0.3.7}/tests/test_empty_turn_skip.py +0 -0
- {virtual_context-0.3.5 → virtual_context-0.3.7}/tests/test_engine_integration.py +0 -0
- {virtual_context-0.3.5 → virtual_context-0.3.7}/tests/test_engine_lookback.py +0 -0
- {virtual_context-0.3.5 → virtual_context-0.3.7}/tests/test_fact_enrichment.py +0 -0
- {virtual_context-0.3.5 → virtual_context-0.3.7}/tests/test_fact_graph_integration.py +0 -0
- {virtual_context-0.3.5 → virtual_context-0.3.7}/tests/test_fact_link_checker.py +0 -0
- {virtual_context-0.3.5 → virtual_context-0.3.7}/tests/test_fact_link_query.py +0 -0
- {virtual_context-0.3.5 → virtual_context-0.3.7}/tests/test_fact_link_types.py +0 -0
- {virtual_context-0.3.5 → virtual_context-0.3.7}/tests/test_fact_links_sqlite.py +0 -0
- {virtual_context-0.3.5 → virtual_context-0.3.7}/tests/test_fill_pass.py +0 -0
- {virtual_context-0.3.5 → virtual_context-0.3.7}/tests/test_format_agnostic.py +0 -0
- {virtual_context-0.3.5 → virtual_context-0.3.7}/tests/test_headless.py +0 -0
- {virtual_context-0.3.5 → virtual_context-0.3.7}/tests/test_history_filter.py +0 -0
- {virtual_context-0.3.5 → virtual_context-0.3.7}/tests/test_idf_retrieval.py +0 -0
- {virtual_context-0.3.5 → virtual_context-0.3.7}/tests/test_ingest_index_integrity.py +0 -0
- {virtual_context-0.3.5 → virtual_context-0.3.7}/tests/test_longmemeval_auth.py +0 -0
- {virtual_context-0.3.5 → virtual_context-0.3.7}/tests/test_mcp_server.py +0 -0
- {virtual_context-0.3.5 → virtual_context-0.3.7}/tests/test_media.py +0 -0
- {virtual_context-0.3.5 → virtual_context-0.3.7}/tests/test_message_filter.py +0 -0
- {virtual_context-0.3.5 → virtual_context-0.3.7}/tests/test_metrics_persistence.py +0 -0
- {virtual_context-0.3.5 → virtual_context-0.3.7}/tests/test_model_catalog.py +0 -0
- {virtual_context-0.3.5 → virtual_context-0.3.7}/tests/test_model_limits.py +0 -0
- {virtual_context-0.3.5 → virtual_context-0.3.7}/tests/test_monitor.py +0 -0
- {virtual_context-0.3.5 → virtual_context-0.3.7}/tests/test_multi_instance.py +0 -0
- {virtual_context-0.3.5 → virtual_context-0.3.7}/tests/test_noop_fact_link_store.py +0 -0
- {virtual_context-0.3.5 → virtual_context-0.3.7}/tests/test_openrouter_provider.py +0 -0
- {virtual_context-0.3.5 → virtual_context-0.3.7}/tests/test_paging.py +0 -0
- {virtual_context-0.3.5 → virtual_context-0.3.7}/tests/test_presets.py +0 -0
- {virtual_context-0.3.5 → virtual_context-0.3.7}/tests/test_prev_context_leak.py +0 -0
- {virtual_context-0.3.5 → virtual_context-0.3.7}/tests/test_provider_adapters.py +0 -0
- {virtual_context-0.3.5 → virtual_context-0.3.7}/tests/test_proxy_dashboard.py +0 -0
- {virtual_context-0.3.5 → virtual_context-0.3.7}/tests/test_proxy_message_filter.py +0 -0
- {virtual_context-0.3.5 → virtual_context-0.3.7}/tests/test_proxy_streaming.py +0 -0
- {virtual_context-0.3.5 → virtual_context-0.3.7}/tests/test_raw_content.py +0 -0
- {virtual_context-0.3.5 → virtual_context-0.3.7}/tests/test_recall_all.py +0 -0
- {virtual_context-0.3.5 → virtual_context-0.3.7}/tests/test_registry_lifecycle.py +0 -0
- {virtual_context-0.3.5 → virtual_context-0.3.7}/tests/test_rrf_scoring.py +0 -0
- {virtual_context-0.3.5 → virtual_context-0.3.7}/tests/test_segmenter.py +0 -0
- {virtual_context-0.3.5 → virtual_context-0.3.7}/tests/test_sender_identity.py +0 -0
- {virtual_context-0.3.5 → virtual_context-0.3.7}/tests/test_session_cache.py +0 -0
- {virtual_context-0.3.5 → virtual_context-0.3.7}/tests/test_session_date.py +0 -0
- {virtual_context-0.3.5 → virtual_context-0.3.7}/tests/test_session_state.py +0 -0
- {virtual_context-0.3.5 → virtual_context-0.3.7}/tests/test_store_recovery.py +0 -0
- {virtual_context-0.3.5 → virtual_context-0.3.7}/tests/test_stub_turn_handling.py +0 -0
- {virtual_context-0.3.5 → virtual_context-0.3.7}/tests/test_supersession.py +0 -0
- {virtual_context-0.3.5 → virtual_context-0.3.7}/tests/test_supersession_migration.py +0 -0
- {virtual_context-0.3.5 → virtual_context-0.3.7}/tests/test_tag_canonicalizer.py +0 -0
- {virtual_context-0.3.5 → virtual_context-0.3.7}/tests/test_tag_consolidator.py +0 -0
- {virtual_context-0.3.5 → virtual_context-0.3.7}/tests/test_tag_splitter.py +0 -0
- {virtual_context-0.3.5 → virtual_context-0.3.7}/tests/test_telemetry.py +0 -0
- {virtual_context-0.3.5 → virtual_context-0.3.7}/tests/test_telemetry_integration.py +0 -0
- {virtual_context-0.3.5 → virtual_context-0.3.7}/tests/test_tool_output_interceptor.py +0 -0
- {virtual_context-0.3.5 → virtual_context-0.3.7}/tests/test_tool_result_filter.py +0 -0
- {virtual_context-0.3.5 → virtual_context-0.3.7}/tests/test_tool_tags.py +0 -0
- {virtual_context-0.3.5 → virtual_context-0.3.7}/tests/test_tui.py +0 -0
- {virtual_context-0.3.5 → virtual_context-0.3.7}/tests/test_turn_grouping.py +0 -0
- {virtual_context-0.3.5 → virtual_context-0.3.7}/tests/test_turn_tag_index.py +0 -0
- {virtual_context-0.3.5 → virtual_context-0.3.7}/tests/test_unified_budget.py +0 -0
- {virtual_context-0.3.5 → virtual_context-0.3.7}/tests/test_upstream_trim.py +0 -0
- {virtual_context-0.3.5 → virtual_context-0.3.7}/tests/test_verb_expansion.py +0 -0
- {virtual_context-0.3.5 → virtual_context-0.3.7}/virtual-context.yaml +0 -0
- {virtual_context-0.3.5 → virtual_context-0.3.7}/virtual-context.yaml.example +0 -0
- {virtual_context-0.3.5 → virtual_context-0.3.7}/virtual_context/cli/__init__.py +0 -0
- {virtual_context-0.3.5 → virtual_context-0.3.7}/virtual_context/cli/main.py +0 -0
- {virtual_context-0.3.5 → virtual_context-0.3.7}/virtual_context/config.py +0 -0
- {virtual_context-0.3.5 → virtual_context-0.3.7}/virtual_context/conversation_identity.py +0 -0
- {virtual_context-0.3.5 → virtual_context-0.3.7}/virtual_context/core/__init__.py +0 -0
- {virtual_context-0.3.5 → virtual_context-0.3.7}/virtual_context/core/embedding_provider.py +0 -0
- {virtual_context-0.3.5 → virtual_context-0.3.7}/virtual_context/core/embedding_tag_generator.py +0 -0
- {virtual_context-0.3.5 → virtual_context-0.3.7}/virtual_context/core/engine_utils.py +0 -0
- {virtual_context-0.3.5 → virtual_context-0.3.7}/virtual_context/core/fact_query.py +0 -0
- {virtual_context-0.3.5 → virtual_context-0.3.7}/virtual_context/core/fts_preprocessor.py +0 -0
- {virtual_context-0.3.5 → virtual_context-0.3.7}/virtual_context/core/math_utils.py +0 -0
- {virtual_context-0.3.5 → virtual_context-0.3.7}/virtual_context/core/model_catalog.py +0 -0
- {virtual_context-0.3.5 → virtual_context-0.3.7}/virtual_context/core/monitor.py +0 -0
- {virtual_context-0.3.5 → virtual_context-0.3.7}/virtual_context/core/paging_manager.py +0 -0
- {virtual_context-0.3.5 → virtual_context-0.3.7}/virtual_context/core/provider_adapters.py +0 -0
- {virtual_context-0.3.5 → virtual_context-0.3.7}/virtual_context/core/retrieval_assembler.py +0 -0
- {virtual_context-0.3.5 → virtual_context-0.3.7}/virtual_context/core/retrieval_scoring.py +0 -0
- {virtual_context-0.3.5 → virtual_context-0.3.7}/virtual_context/core/tag_canonicalizer.py +0 -0
- {virtual_context-0.3.5 → virtual_context-0.3.7}/virtual_context/core/tag_consolidator.py +0 -0
- {virtual_context-0.3.5 → virtual_context-0.3.7}/virtual_context/core/tag_scoring.py +0 -0
- {virtual_context-0.3.5 → virtual_context-0.3.7}/virtual_context/core/tag_splitter.py +0 -0
- {virtual_context-0.3.5 → virtual_context-0.3.7}/virtual_context/core/telemetry.py +0 -0
- {virtual_context-0.3.5 → virtual_context-0.3.7}/virtual_context/core/tool_query.py +0 -0
- {virtual_context-0.3.5 → virtual_context-0.3.7}/virtual_context/core/turn_tag_index.py +0 -0
- {virtual_context-0.3.5 → virtual_context-0.3.7}/virtual_context/data/anthropic-tokenizer/tokenizer.json +0 -0
- {virtual_context-0.3.5 → virtual_context-0.3.7}/virtual_context/data/models.yaml +0 -0
- {virtual_context-0.3.5 → virtual_context-0.3.7}/virtual_context/ingest/__init__.py +0 -0
- {virtual_context-0.3.5 → virtual_context-0.3.7}/virtual_context/ingest/curator.py +0 -0
- {virtual_context-0.3.5 → virtual_context-0.3.7}/virtual_context/ingest/date_resolver.py +0 -0
- {virtual_context-0.3.5 → virtual_context-0.3.7}/virtual_context/ingest/parsers.py +0 -0
- {virtual_context-0.3.5 → virtual_context-0.3.7}/virtual_context/ingest/supersession.py +0 -0
- {virtual_context-0.3.5 → virtual_context-0.3.7}/virtual_context/mcp/__init__.py +0 -0
- {virtual_context-0.3.5 → virtual_context-0.3.7}/virtual_context/model_limits.py +0 -0
- {virtual_context-0.3.5 → virtual_context-0.3.7}/virtual_context/openclaw/virtual-context.mjs +0 -0
- {virtual_context-0.3.5 → virtual_context-0.3.7}/virtual_context/patterns.py +0 -0
- {virtual_context-0.3.5 → virtual_context-0.3.7}/virtual_context/presets/__init__.py +0 -0
- {virtual_context-0.3.5 → virtual_context-0.3.7}/virtual_context/presets/agentic.py +0 -0
- {virtual_context-0.3.5 → virtual_context-0.3.7}/virtual_context/presets/base.py +0 -0
- {virtual_context-0.3.5 → virtual_context-0.3.7}/virtual_context/presets/coding.py +0 -0
- {virtual_context-0.3.5 → virtual_context-0.3.7}/virtual_context/providers/__init__.py +0 -0
- {virtual_context-0.3.5 → virtual_context-0.3.7}/virtual_context/providers/anthropic.py +0 -0
- {virtual_context-0.3.5 → virtual_context-0.3.7}/virtual_context/providers/base.py +0 -0
- {virtual_context-0.3.5 → virtual_context-0.3.7}/virtual_context/providers/generic_openai.py +0 -0
- {virtual_context-0.3.5 → virtual_context-0.3.7}/virtual_context/providers/ollama_native.py +0 -0
- {virtual_context-0.3.5 → virtual_context-0.3.7}/virtual_context/proxy/__init__.py +0 -0
- {virtual_context-0.3.5 → virtual_context-0.3.7}/virtual_context/proxy/_envelope.py +0 -0
- {virtual_context-0.3.5 → virtual_context-0.3.7}/virtual_context/proxy/dashboard.html +0 -0
- {virtual_context-0.3.5 → virtual_context-0.3.7}/virtual_context/proxy/dashboard.py +0 -0
- {virtual_context-0.3.5 → virtual_context-0.3.7}/virtual_context/proxy/helpers.py +0 -0
- {virtual_context-0.3.5 → virtual_context-0.3.7}/virtual_context/proxy/media.py +0 -0
- {virtual_context-0.3.5 → virtual_context-0.3.7}/virtual_context/proxy/message_filter.py +0 -0
- {virtual_context-0.3.5 → virtual_context-0.3.7}/virtual_context/proxy/multi.py +0 -0
- {virtual_context-0.3.5 → virtual_context-0.3.7}/virtual_context/proxy/session_cache.py +0 -0
- {virtual_context-0.3.5 → virtual_context-0.3.7}/virtual_context/proxy/static/android-chrome-192x192.png +0 -0
- {virtual_context-0.3.5 → virtual_context-0.3.7}/virtual_context/proxy/static/android-chrome-512x512.png +0 -0
- {virtual_context-0.3.5 → virtual_context-0.3.7}/virtual_context/proxy/static/apple-touch-icon.png +0 -0
- {virtual_context-0.3.5 → virtual_context-0.3.7}/virtual_context/proxy/static/favicon-16x16.png +0 -0
- {virtual_context-0.3.5 → virtual_context-0.3.7}/virtual_context/proxy/static/favicon-32x32.png +0 -0
- {virtual_context-0.3.5 → virtual_context-0.3.7}/virtual_context/proxy/static/favicon.ico +0 -0
- {virtual_context-0.3.5 → virtual_context-0.3.7}/virtual_context/proxy/static/site.webmanifest +0 -0
- {virtual_context-0.3.5 → virtual_context-0.3.7}/virtual_context/proxy/tool_output_interceptor.py +0 -0
- {virtual_context-0.3.5 → virtual_context-0.3.7}/virtual_context/proxy/vcattach.py +0 -0
- {virtual_context-0.3.5 → virtual_context-0.3.7}/virtual_context/storage/__init__.py +0 -0
- {virtual_context-0.3.5 → virtual_context-0.3.7}/virtual_context/storage/falkordb.py +0 -0
- {virtual_context-0.3.5 → virtual_context-0.3.7}/virtual_context/storage/helpers.py +0 -0
- {virtual_context-0.3.5 → virtual_context-0.3.7}/virtual_context/storage/neo4j.py +0 -0
- {virtual_context-0.3.5 → virtual_context-0.3.7}/virtual_context/storage/noop_fact_link_store.py +0 -0
- {virtual_context-0.3.5 → virtual_context-0.3.7}/virtual_context/token_counter.py +0 -0
- {virtual_context-0.3.5 → virtual_context-0.3.7}/virtual_context/tui/__init__.py +0 -0
- {virtual_context-0.3.5 → virtual_context-0.3.7}/virtual_context/tui/app.py +0 -0
- {virtual_context-0.3.5 → virtual_context-0.3.7}/virtual_context/tui/chat.tcss +0 -0
- {virtual_context-0.3.5 → virtual_context-0.3.7}/virtual_context/tui/chat_provider.py +0 -0
- {virtual_context-0.3.5 → virtual_context-0.3.7}/virtual_context/tui/headless.py +0 -0
- {virtual_context-0.3.5 → virtual_context-0.3.7}/virtual_context/tui/modals/__init__.py +0 -0
- {virtual_context-0.3.5 → virtual_context-0.3.7}/virtual_context/tui/modals/turn_inspector.py +0 -0
- {virtual_context-0.3.5 → virtual_context-0.3.7}/virtual_context/tui/state.py +0 -0
- {virtual_context-0.3.5 → virtual_context-0.3.7}/virtual_context/tui/widgets/__init__.py +0 -0
- {virtual_context-0.3.5 → virtual_context-0.3.7}/virtual_context/tui/widgets/budget_bar.py +0 -0
- {virtual_context-0.3.5 → virtual_context-0.3.7}/virtual_context/tui/widgets/chat_view.py +0 -0
- {virtual_context-0.3.5 → virtual_context-0.3.7}/virtual_context/tui/widgets/input_box.py +0 -0
- {virtual_context-0.3.5 → virtual_context-0.3.7}/virtual_context/tui/widgets/tag_panel.py +0 -0
- {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.
|
|
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 @@ 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
|
|
70
|
+
"""Search canonical full_text through the CompositeStore delegate.
|
|
71
71
|
|
|
72
|
-
Validates that the CompositeStore.
|
|
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, "
|
|
76
|
+
_search = getattr(store, "search_canonical_full_text", None)
|
|
77
77
|
assert _search is not None, (
|
|
78
|
-
"
|
|
79
|
-
"CompositeStore delegation missing
|
|
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
|
|
65
|
-
|
|
66
|
-
|
|
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
|
|
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():
|