vectorwave 0.2.2__tar.gz → 0.2.3__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 (91) hide show
  1. {vectorwave-0.2.2/src/vectorwave.egg-info → vectorwave-0.2.3}/PKG-INFO +1 -1
  2. {vectorwave-0.2.2 → vectorwave-0.2.3}/pyproject.toml +1 -1
  3. vectorwave-0.2.3/src/tests/utils/test_replay_source.py +140 -0
  4. {vectorwave-0.2.2 → vectorwave-0.2.3}/src/vectorwave/core/decorator.py +7 -4
  5. {vectorwave-0.2.2 → vectorwave-0.2.3}/src/vectorwave/database/db.py +5 -0
  6. {vectorwave-0.2.2 → vectorwave-0.2.3}/src/vectorwave/monitoring/tracer.py +3 -1
  7. {vectorwave-0.2.2 → vectorwave-0.2.3}/src/vectorwave/search/execution_search.py +31 -0
  8. vectorwave-0.2.3/src/vectorwave/utils/context.py +4 -0
  9. {vectorwave-0.2.2 → vectorwave-0.2.3}/src/vectorwave/utils/replayer.py +8 -0
  10. {vectorwave-0.2.2 → vectorwave-0.2.3}/src/vectorwave/utils/replayer_semantic.py +6 -0
  11. {vectorwave-0.2.2 → vectorwave-0.2.3/src/vectorwave.egg-info}/PKG-INFO +1 -1
  12. {vectorwave-0.2.2 → vectorwave-0.2.3}/src/vectorwave.egg-info/SOURCES.txt +2 -0
  13. {vectorwave-0.2.2 → vectorwave-0.2.3}/LICENSE +0 -0
  14. {vectorwave-0.2.2 → vectorwave-0.2.3}/MANIFEST.in +0 -0
  15. {vectorwave-0.2.2 → vectorwave-0.2.3}/NOTICE +0 -0
  16. {vectorwave-0.2.2 → vectorwave-0.2.3}/Readme.md +0 -0
  17. {vectorwave-0.2.2 → vectorwave-0.2.3}/setup.cfg +0 -0
  18. {vectorwave-0.2.2 → vectorwave-0.2.3}/src/tests/__init__.py +0 -0
  19. {vectorwave-0.2.2 → vectorwave-0.2.3}/src/tests/batch/__init__.py +0 -0
  20. {vectorwave-0.2.2 → vectorwave-0.2.3}/src/tests/batch/test_batch.py +0 -0
  21. {vectorwave-0.2.2 → vectorwave-0.2.3}/src/tests/conftest.py +0 -0
  22. {vectorwave-0.2.2 → vectorwave-0.2.3}/src/tests/core/__init__.py +0 -0
  23. {vectorwave-0.2.2 → vectorwave-0.2.3}/src/tests/core/llm/__init__.py +0 -0
  24. {vectorwave-0.2.2 → vectorwave-0.2.3}/src/tests/core/llm/test_token_usage.py +0 -0
  25. {vectorwave-0.2.2 → vectorwave-0.2.3}/src/tests/core/test_decorator.py +0 -0
  26. {vectorwave-0.2.2 → vectorwave-0.2.3}/src/tests/core/test_semantic_caching.py +0 -0
  27. {vectorwave-0.2.2 → vectorwave-0.2.3}/src/tests/database/__init__.py +0 -0
  28. {vectorwave-0.2.2 → vectorwave-0.2.3}/src/tests/database/test_archiver.py +0 -0
  29. {vectorwave-0.2.2 → vectorwave-0.2.3}/src/tests/database/test_dataset.py +0 -0
  30. {vectorwave-0.2.2 → vectorwave-0.2.3}/src/tests/database/test_db.py +0 -0
  31. {vectorwave-0.2.2 → vectorwave-0.2.3}/src/tests/database/test_db_search.py +0 -0
  32. {vectorwave-0.2.2 → vectorwave-0.2.3}/src/tests/exception/__init__.py +0 -0
  33. {vectorwave-0.2.2 → vectorwave-0.2.3}/src/tests/models/__init__.py +0 -0
  34. {vectorwave-0.2.2 → vectorwave-0.2.3}/src/tests/models/test_db_config.py +0 -0
  35. {vectorwave-0.2.2 → vectorwave-0.2.3}/src/tests/monitoring/__init__.py +0 -0
  36. {vectorwave-0.2.2 → vectorwave-0.2.3}/src/tests/monitoring/alert/__init__.py +0 -0
  37. {vectorwave-0.2.2 → vectorwave-0.2.3}/src/tests/monitoring/alert/test_alerter.py +0 -0
  38. {vectorwave-0.2.2 → vectorwave-0.2.3}/src/tests/monitoring/test_async_trace.py +0 -0
  39. {vectorwave-0.2.2 → vectorwave-0.2.3}/src/tests/monitoring/test_tracer.py +0 -0
  40. {vectorwave-0.2.2 → vectorwave-0.2.3}/src/tests/prediction/__init__.py +0 -0
  41. {vectorwave-0.2.2 → vectorwave-0.2.3}/src/tests/search/__init__.py +0 -0
  42. {vectorwave-0.2.2 → vectorwave-0.2.3}/src/tests/search/test_execution_search.py +0 -0
  43. {vectorwave-0.2.2 → vectorwave-0.2.3}/src/tests/utils/__init__.py +0 -0
  44. {vectorwave-0.2.2 → vectorwave-0.2.3}/src/tests/utils/test_function_cahe.py +0 -0
  45. {vectorwave-0.2.2 → vectorwave-0.2.3}/src/tests/utils/test_replayer.py +0 -0
  46. {vectorwave-0.2.2 → vectorwave-0.2.3}/src/tests/utils/test_return_caching.py +0 -0
  47. {vectorwave-0.2.2 → vectorwave-0.2.3}/src/tests/utils/test_status.py +0 -0
  48. {vectorwave-0.2.2 → vectorwave-0.2.3}/src/tests/vectorizer/__init__.py +0 -0
  49. {vectorwave-0.2.2 → vectorwave-0.2.3}/src/vectorwave/__init__.py +0 -0
  50. {vectorwave-0.2.2 → vectorwave-0.2.3}/src/vectorwave/batch/__init__.py +0 -0
  51. {vectorwave-0.2.2 → vectorwave-0.2.3}/src/vectorwave/batch/batch.py +0 -0
  52. {vectorwave-0.2.2 → vectorwave-0.2.3}/src/vectorwave/core/__init__.py +0 -0
  53. {vectorwave-0.2.2 → vectorwave-0.2.3}/src/vectorwave/core/core.py +0 -0
  54. {vectorwave-0.2.2 → vectorwave-0.2.3}/src/vectorwave/core/generator.py +0 -0
  55. {vectorwave-0.2.2 → vectorwave-0.2.3}/src/vectorwave/core/llm/__init__.py +0 -0
  56. {vectorwave-0.2.2 → vectorwave-0.2.3}/src/vectorwave/core/llm/base.py +0 -0
  57. {vectorwave-0.2.2 → vectorwave-0.2.3}/src/vectorwave/core/llm/factory.py +0 -0
  58. {vectorwave-0.2.2 → vectorwave-0.2.3}/src/vectorwave/core/llm/openai_client.py +0 -0
  59. {vectorwave-0.2.2 → vectorwave-0.2.3}/src/vectorwave/database/__init__.py +0 -0
  60. {vectorwave-0.2.2 → vectorwave-0.2.3}/src/vectorwave/database/archiver.py +0 -0
  61. {vectorwave-0.2.2 → vectorwave-0.2.3}/src/vectorwave/database/dataset.py +0 -0
  62. {vectorwave-0.2.2 → vectorwave-0.2.3}/src/vectorwave/database/db_search.py +0 -0
  63. {vectorwave-0.2.2 → vectorwave-0.2.3}/src/vectorwave/exception/__init__.py +0 -0
  64. {vectorwave-0.2.2 → vectorwave-0.2.3}/src/vectorwave/exception/exceptions.py +0 -0
  65. {vectorwave-0.2.2 → vectorwave-0.2.3}/src/vectorwave/models/__init__.py +0 -0
  66. {vectorwave-0.2.2 → vectorwave-0.2.3}/src/vectorwave/models/db_config.py +0 -0
  67. {vectorwave-0.2.2 → vectorwave-0.2.3}/src/vectorwave/monitoring/__init__.py +0 -0
  68. {vectorwave-0.2.2 → vectorwave-0.2.3}/src/vectorwave/monitoring/alert/__init__.py +0 -0
  69. {vectorwave-0.2.2 → vectorwave-0.2.3}/src/vectorwave/monitoring/alert/base.py +0 -0
  70. {vectorwave-0.2.2 → vectorwave-0.2.3}/src/vectorwave/monitoring/alert/factory.py +0 -0
  71. {vectorwave-0.2.2 → vectorwave-0.2.3}/src/vectorwave/monitoring/alert/null_alerter.py +0 -0
  72. {vectorwave-0.2.2 → vectorwave-0.2.3}/src/vectorwave/monitoring/alert/webhook_alerter.py +0 -0
  73. {vectorwave-0.2.2 → vectorwave-0.2.3}/src/vectorwave/monitoring/monitoring.py +0 -0
  74. {vectorwave-0.2.2 → vectorwave-0.2.3}/src/vectorwave/prediction/__init__.py +0 -0
  75. {vectorwave-0.2.2 → vectorwave-0.2.3}/src/vectorwave/prediction/predictor.py +0 -0
  76. {vectorwave-0.2.2 → vectorwave-0.2.3}/src/vectorwave/search/__init__.py +0 -0
  77. {vectorwave-0.2.2 → vectorwave-0.2.3}/src/vectorwave/search/extended_search.py +0 -0
  78. {vectorwave-0.2.2 → vectorwave-0.2.3}/src/vectorwave/search/rag_search.py +0 -0
  79. {vectorwave-0.2.2 → vectorwave-0.2.3}/src/vectorwave/utils/__init__.py +0 -0
  80. {vectorwave-0.2.2 → vectorwave-0.2.3}/src/vectorwave/utils/function_cache.py +0 -0
  81. {vectorwave-0.2.2 → vectorwave-0.2.3}/src/vectorwave/utils/healer.py +0 -0
  82. {vectorwave-0.2.2 → vectorwave-0.2.3}/src/vectorwave/utils/return_caching_utils.py +0 -0
  83. {vectorwave-0.2.2 → vectorwave-0.2.3}/src/vectorwave/utils/status.py +0 -0
  84. {vectorwave-0.2.2 → vectorwave-0.2.3}/src/vectorwave/vectorizer/__init__.py +0 -0
  85. {vectorwave-0.2.2 → vectorwave-0.2.3}/src/vectorwave/vectorizer/base.py +0 -0
  86. {vectorwave-0.2.2 → vectorwave-0.2.3}/src/vectorwave/vectorizer/factory.py +0 -0
  87. {vectorwave-0.2.2 → vectorwave-0.2.3}/src/vectorwave/vectorizer/huggingface_vectorizer.py +0 -0
  88. {vectorwave-0.2.2 → vectorwave-0.2.3}/src/vectorwave/vectorizer/openai_vectorizer.py +0 -0
  89. {vectorwave-0.2.2 → vectorwave-0.2.3}/src/vectorwave.egg-info/dependency_links.txt +0 -0
  90. {vectorwave-0.2.2 → vectorwave-0.2.3}/src/vectorwave.egg-info/requires.txt +0 -0
  91. {vectorwave-0.2.2 → vectorwave-0.2.3}/src/vectorwave.egg-info/top_level.txt +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: vectorwave
3
- Version: 0.2.2
3
+ Version: 0.2.3
4
4
  Summary: VectorWave: Seamless Auto-Vectorization Framework
5
5
  Author-email: junyeonggim <junyeonggim5@gmail.com>
6
6
  License-Expression: MIT
@@ -4,7 +4,7 @@ build-backend = "setuptools.build_meta"
4
4
 
5
5
  [project]
6
6
  name = "vectorwave"
7
- version = "0.2.02"
7
+ version = "0.2.03"
8
8
  authors = [
9
9
  { name = "junyeonggim", email = "junyeonggim5@gmail.com" },
10
10
  ]
@@ -0,0 +1,140 @@
1
+ import pytest
2
+ import sys
3
+ from unittest.mock import MagicMock, patch
4
+ from vectorwave import vectorize, search_executions
5
+ from vectorwave.utils.replayer import VectorWaveReplayer
6
+ from vectorwave.models.db_config import WeaviateSettings
7
+
8
+ # 1. Dummy function for testing
9
+ @vectorize(unique_id="test_replay_tagging")
10
+ def calc_add(a: int, b: int):
11
+ """Simple addition function for testing replay tags."""
12
+ return a + b
13
+
14
+ @pytest.fixture
15
+ def mock_replay_deps(monkeypatch):
16
+ """Mocks dependencies for Replay Source testing."""
17
+ # Mock Settings
18
+ mock_settings = WeaviateSettings(
19
+ EXECUTION_COLLECTION_NAME="VectorWaveExecutions",
20
+ GOLDEN_COLLECTION_NAME="VectorWaveGoldenDataset"
21
+ )
22
+ mock_get_settings = MagicMock(return_value=mock_settings)
23
+
24
+ # Mock Batch Manager (to verify logs)
25
+ mock_batch = MagicMock()
26
+ mock_batch.add_object = MagicMock()
27
+ mock_get_batch = MagicMock(return_value=mock_batch)
28
+
29
+ # Mock DB Client (for Replayer initialization)
30
+ mock_client = MagicMock()
31
+ mock_collection = MagicMock()
32
+ mock_client.collections.get.return_value = mock_collection
33
+ mock_get_client = MagicMock(return_value=mock_client)
34
+
35
+ # --- [수정] Patch dependencies where they are USED, not just defined ---
36
+
37
+ # 1. Patch for Replayer (vectorwave/utils/replayer.py)
38
+ monkeypatch.setattr("vectorwave.utils.replayer.get_cached_client", mock_get_client)
39
+ monkeypatch.setattr("vectorwave.utils.replayer.get_weaviate_settings", mock_get_settings)
40
+
41
+ # 2. Patch for Database (vectorwave/database/db.py) - 안전장치
42
+ monkeypatch.setattr("vectorwave.database.db.get_cached_client", mock_get_client)
43
+
44
+ # 3. Patch for Config (vectorwave/models/db_config.py) - 안전장치
45
+ monkeypatch.setattr("vectorwave.models.db_config.get_weaviate_settings", mock_get_settings)
46
+
47
+ # 4. Patch batch manager for Decorator & Tracer
48
+ monkeypatch.setattr("vectorwave.core.decorator.get_batch_manager", mock_get_batch)
49
+ monkeypatch.setattr("vectorwave.monitoring.tracer.get_batch_manager", mock_get_batch)
50
+
51
+ # 5. Patch search_executions in THIS test file
52
+ mock_search = MagicMock()
53
+ monkeypatch.setattr(sys.modules[__name__], "search_executions", mock_search)
54
+
55
+ return {
56
+ "batch": mock_batch,
57
+ "search": mock_search,
58
+ "client": mock_client
59
+ }
60
+
61
+ def test_execution_source_tagging(mock_replay_deps):
62
+ """
63
+ Verification Scenario:
64
+ 1. Realtime Execution -> Check if saved to DB as 'REALTIME'
65
+ 2. Replay Execution -> Check if saved to DB as 'REPLAY'
66
+ """
67
+ mock_batch = mock_replay_deps["batch"]
68
+
69
+ # ---------------------------------------------------------
70
+ # Case 1: Realtime Execution
71
+ # ---------------------------------------------------------
72
+ print("\n🚀 1. Running Realtime Execution...")
73
+ calc_add(10, 20)
74
+
75
+ # Check if log was sent to BatchManager
76
+ assert mock_batch.add_object.called
77
+
78
+ # Get the latest call args
79
+ args, kwargs = mock_batch.add_object.call_args
80
+ props = kwargs['properties']
81
+
82
+ print(f" [Log Check] Source: {props.get('exec_source')}")
83
+
84
+ # Verify exec_source is 'REALTIME'
85
+ assert props.get("exec_source") == "REALTIME"
86
+ assert props.get("status") == "SUCCESS"
87
+
88
+ # ---------------------------------------------------------
89
+ # Case 2: Replay Execution
90
+ # ---------------------------------------------------------
91
+ print("\n🔄 2. Running Replay...")
92
+
93
+ # Prepare dummy log for Replayer to fetch
94
+ dummy_log_obj = MagicMock()
95
+ dummy_log_obj.uuid = "old-uuid-123"
96
+ dummy_log_obj.properties = {
97
+ "function_name": "calc_add",
98
+ "a": 10,
99
+ "b": 20,
100
+ "return_value": "30",
101
+ "exec_source": "REALTIME"
102
+ }
103
+
104
+ # Replayer uses client.collections.get().query.fetch_objects()
105
+ mock_collection = mock_replay_deps["client"].collections.get.return_value
106
+ mock_collection.query.fetch_objects.return_value.objects = [dummy_log_obj]
107
+
108
+ # Also need to mock import_module since Replayer imports the function dynamically
109
+ with patch("vectorwave.utils.replayer.importlib.import_module") as mock_import:
110
+ mock_module = MagicMock()
111
+ # Set the function on the mock module
112
+ setattr(mock_module, "calc_add", calc_add)
113
+ mock_import.return_value = mock_module
114
+
115
+ replayer = VectorWaveReplayer()
116
+
117
+ # Reset batch mock to capture only replay log
118
+ mock_batch.add_object.reset_mock()
119
+
120
+ # Execute Replay
121
+ result = replayer.replay(
122
+ function_full_name="src.tests.utils.test_replay_source.calc_add",
123
+ limit=1
124
+ )
125
+
126
+ assert result['total'] > 0, "Replay should have executed at least 1 test."
127
+
128
+ # Check if new log was sent to BatchManager
129
+ assert mock_batch.add_object.called
130
+
131
+ # Get the latest call args (from Replay execution)
132
+ args, kwargs = mock_batch.add_object.call_args
133
+ replay_props = kwargs['properties']
134
+
135
+ print(f" [Log Check] Source: {replay_props.get('exec_source')}")
136
+
137
+ # Verify exec_source is 'REPLAY'
138
+ assert replay_props.get("exec_source") == "REPLAY"
139
+
140
+ print("\n✅ All tests passed! Execution Source tagging is working.")
@@ -11,6 +11,7 @@ from ..monitoring.tracer import trace_root, trace_span
11
11
  from ..utils.function_cache import function_cache_manager
12
12
  from ..utils.return_caching_utils import _check_and_return_cached_result
13
13
  from ..vectorizer.factory import get_vectorizer
14
+ from ..utils.context import execution_source_context
14
15
 
15
16
  logger = logging.getLogger(__name__)
16
17
 
@@ -53,7 +54,7 @@ def vectorize(search_description: Optional[str] = None,
53
54
  func_uuid = generate_uuid5(func_identifier)
54
55
 
55
56
  # Prepare attributes to capture
56
- final_attributes = ['function_uuid', 'team', 'priority', 'run_id']
57
+ final_attributes = ['function_uuid', 'team', 'priority', 'run_id', 'exec_source']
57
58
  if attributes_to_capture:
58
59
  for attr in attributes_to_capture:
59
60
  if attr not in final_attributes:
@@ -145,7 +146,7 @@ def vectorize(search_description: Optional[str] = None,
145
146
  async def inner_wrapper(*args, **kwargs):
146
147
  # Remove injected tags from kwargs before calling original func
147
148
  clean_kwargs = {k: v for k, v in kwargs.items() if
148
- k not in valid_execution_tags and k != 'function_uuid'}
149
+ k not in valid_execution_tags and k != 'function_uuid' and k != 'exec_source'}
149
150
  return await func(*args, **clean_kwargs)
150
151
 
151
152
  @wraps(func)
@@ -157,6 +158,7 @@ def vectorize(search_description: Optional[str] = None,
157
158
  full_kwargs = kwargs.copy()
158
159
  full_kwargs.update(valid_execution_tags)
159
160
  full_kwargs['function_uuid'] = func_uuid
161
+ full_kwargs['exec_source'] = execution_source_context.get()
160
162
  return await inner_wrapper(*args, **full_kwargs)
161
163
 
162
164
  return outer_wrapper
@@ -167,7 +169,7 @@ def vectorize(search_description: Optional[str] = None,
167
169
  @wraps(func)
168
170
  def inner_wrapper(*args, **kwargs):
169
171
  clean_kwargs = {k: v for k, v in kwargs.items() if
170
- k not in valid_execution_tags and k != 'function_uuid'}
172
+ k not in valid_execution_tags and k != 'function_uuid' and k != 'exec_source'}
171
173
  return func(*args, **clean_kwargs)
172
174
 
173
175
  @wraps(func)
@@ -179,8 +181,9 @@ def vectorize(search_description: Optional[str] = None,
179
181
  full_kwargs = kwargs.copy()
180
182
  full_kwargs.update(valid_execution_tags)
181
183
  full_kwargs['function_uuid'] = func_uuid
184
+ full_kwargs['exec_source'] = execution_source_context.get()
182
185
  return inner_wrapper(*args, **full_kwargs)
183
186
 
184
187
  return outer_wrapper
185
188
 
186
- return decorator
189
+ return decorator
@@ -282,6 +282,11 @@ def create_execution_schema(client: weaviate.WeaviateClient, settings: WeaviateS
282
282
  name="return_value",
283
283
  data_type=wvc.DataType.TEXT,
284
284
  description="The JSON-serialized or str() representation of the function's return value"
285
+ ),
286
+ wvc.Property(
287
+ name="exec_source",
288
+ data_type=wvc.DataType.TEXT,
289
+ description="Source of execution: 'REALTIME' (User traffic) or 'REPLAY' (Regression Test)"
285
290
  )
286
291
  ]
287
292
 
@@ -15,6 +15,7 @@ from ..models.db_config import get_weaviate_settings, WeaviateSettings
15
15
  from .alert.factory import get_alerter
16
16
  from ..vectorizer.factory import get_vectorizer
17
17
  from ..database.db_search import check_semantic_drift
18
+ from ..utils.context import execution_source_context
18
19
 
19
20
  # Create module-level logger
20
21
  logger = logging.getLogger(__name__)
@@ -137,7 +138,8 @@ def _create_span_properties(
137
138
  "status": status,
138
139
  "error_message": error_msg,
139
140
  "error_code": error_code,
140
- "return_value": return_value_to_log
141
+ "return_value": return_value_to_log,
142
+ "exec_source": execution_source_context.get()
141
143
  }
142
144
 
143
145
  if tracer.settings.global_custom_values:
@@ -121,3 +121,34 @@ def find_by_trace_id(trace_id: str, limit: int = 100) -> List[Dict[str, Any]]:
121
121
  sort_ascending=True, # Sort chronologically
122
122
  limit=limit
123
123
  )
124
+
125
+
126
+ def find_replay_executions(
127
+ limit: int = 20,
128
+ status: Optional[str] = None,
129
+ function_name: Optional[str] = None
130
+ ) -> List[Dict[str, Any]]:
131
+ """
132
+ Searches specifically for logs generated during a Replay session.
133
+
134
+ Args:
135
+ limit: Max number of logs to retrieve.
136
+ status: Optional filter for 'SUCCESS' or 'ERROR'.
137
+ function_name: Optional filter for specific function name.
138
+ """
139
+ logger.info(f"\n--- Searching for REPLAY Executions (Status: {status}, Func: {function_name}) ---")
140
+
141
+ filters = {"exec_source": "REPLAY"}
142
+
143
+ if status:
144
+ filters["status"] = status
145
+
146
+ if function_name:
147
+ filters["function_name"] = function_name
148
+
149
+ return find_executions(
150
+ filters=filters,
151
+ sort_by="timestamp_utc",
152
+ sort_ascending=False,
153
+ limit=limit
154
+ )
@@ -0,0 +1,4 @@
1
+ from contextvars import ContextVar
2
+
3
+ #default is realtime context
4
+ execution_source_context: ContextVar[str] = ContextVar("execution_source", default="REALTIME")
@@ -13,6 +13,7 @@ import weaviate.classes.query as wvc_query
13
13
  from ..database.db import get_cached_client
14
14
  from ..models.db_config import get_weaviate_settings
15
15
  from ..monitoring.tracer import _mask_and_serialize
16
+ from .context import execution_source_context
16
17
 
17
18
  logger = logging.getLogger(__name__)
18
19
 
@@ -78,7 +79,10 @@ class VectorWaveReplayer:
78
79
  # [FIX] Extract only valid arguments for the target function
79
80
  inputs = self._extract_inputs(raw_inputs, target_func)
80
81
 
82
+ token = None
81
83
  try:
84
+ token = execution_source_context.set("REPLAY")
85
+
82
86
  # 3. Function Re-execution
83
87
  if is_async_func:
84
88
  actual_output = asyncio.run(target_func(**inputs))
@@ -127,6 +131,10 @@ class VectorWaveReplayer:
127
131
  "traceback": traceback.format_exc()
128
132
  })
129
133
 
134
+ finally:
135
+ if token:
136
+ execution_source_context.reset(token)
137
+
130
138
  logger.info(f"Replay Finished. Passed: {results['passed']}, Failed: {results['failed']}")
131
139
  return results
132
140
 
@@ -6,6 +6,8 @@ import math
6
6
  import asyncio
7
7
  import inspect
8
8
  from typing import Any, Dict, List, Optional
9
+
10
+ from .context import execution_source_context
9
11
  from ..core.llm.factory import get_llm_client
10
12
 
11
13
  import weaviate.classes.query as wvc_query
@@ -88,12 +90,16 @@ class SemanticReplayer(VectorWaveReplayer):
88
90
  inputs = self._extract_inputs(raw_inputs, target_func)
89
91
 
90
92
  try:
93
+ token = execution_source_context.set("REPLAY")
91
94
  # 3. Function Re-execution
92
95
  if is_async_func:
93
96
  actual_output = asyncio.run(target_func(**inputs))
94
97
  else:
95
98
  actual_output = target_func(**inputs)
96
99
 
100
+ if token:
101
+ execution_source_context.reset(token)
102
+
97
103
  # 4. Result Validation (Semantic Comparison)
98
104
  is_match, match_reason = self._compare_results_semantic(
99
105
  expected_output,
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: vectorwave
3
- Version: 0.2.2
3
+ Version: 0.2.3
4
4
  Summary: VectorWave: Seamless Auto-Vectorization Framework
5
5
  Author-email: junyeonggim <junyeonggim5@gmail.com>
6
6
  License-Expression: MIT
@@ -30,6 +30,7 @@ src/tests/search/__init__.py
30
30
  src/tests/search/test_execution_search.py
31
31
  src/tests/utils/__init__.py
32
32
  src/tests/utils/test_function_cahe.py
33
+ src/tests/utils/test_replay_source.py
33
34
  src/tests/utils/test_replayer.py
34
35
  src/tests/utils/test_return_caching.py
35
36
  src/tests/utils/test_status.py
@@ -74,6 +75,7 @@ src/vectorwave/search/execution_search.py
74
75
  src/vectorwave/search/extended_search.py
75
76
  src/vectorwave/search/rag_search.py
76
77
  src/vectorwave/utils/__init__.py
78
+ src/vectorwave/utils/context.py
77
79
  src/vectorwave/utils/function_cache.py
78
80
  src/vectorwave/utils/healer.py
79
81
  src/vectorwave/utils/replayer.py
File without changes
File without changes
File without changes
File without changes
File without changes