satif-ai 0.2.5__tar.gz → 0.2.7__tar.gz

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.3
2
2
  Name: satif-ai
3
- Version: 0.2.5
3
+ Version: 0.2.7
4
4
  Summary: AI Agents for Satif
5
5
  License: MIT
6
6
  Author: Bryan Djafer
@@ -1,6 +1,6 @@
1
1
  [project]
2
2
  name = "satif-ai"
3
- version = "0.2.5"
3
+ version = "0.2.7"
4
4
  description = "AI Agents for Satif"
5
5
  authors = [
6
6
  {name = "Bryan Djafer", email = "bryan.djafer@syncpulse.fr"}
@@ -1,8 +1,9 @@
1
1
  import base64
2
2
  import os
3
3
  import re
4
+ from collections import defaultdict
4
5
  from pathlib import Path
5
- from typing import Dict, List, Optional, Union
6
+ from typing import Any, Dict, List, Optional, Union
6
7
 
7
8
  from agents import Agent, Runner, function_tool
8
9
  from agents.mcp.server import MCPServer
@@ -18,6 +19,37 @@ OUTPUT_TARGET_FILES: Optional[Dict[Union[str, Path], str]] = None
18
19
  SCHEMA_ONLY: Optional[bool] = None
19
20
 
20
21
 
22
+ def _format_comparison_output(
23
+ comparison_result: Dict[str, Any],
24
+ schema_only_mode: Optional[bool],
25
+ source_file_display_name: str,
26
+ target_file_display_name: str,
27
+ ) -> str:
28
+ """
29
+ Formats the comparison result string, with special handling for schema_only mode
30
+ where files are equivalent due to being empty.
31
+ """
32
+ base_message_prefix = f"Comparison for {source_file_display_name} [SOURCE] with {target_file_display_name} [TARGET]:"
33
+
34
+ if schema_only_mode is True and comparison_result.get("are_equivalent") is True:
35
+ details = comparison_result.get("details", {})
36
+ row_comparison = details.get("row_comparison", {})
37
+
38
+ row_count1 = row_comparison.get("row_count1")
39
+ row_count2 = row_comparison.get("row_count2")
40
+
41
+ if (
42
+ isinstance(row_count1, (int, float))
43
+ and row_count1 == 0
44
+ and isinstance(row_count2, (int, float))
45
+ and row_count2 == 0
46
+ ):
47
+ return f"{base_message_prefix} Files have the same headers but are both empty (no data rows). This should not happen. Please verify the instructions and try again."
48
+
49
+ # Default formatting if the special condition isn't met
50
+ return f"{base_message_prefix} {comparison_result}"
51
+
52
+
21
53
  @function_tool
22
54
  async def execute_transformation(code: str) -> str:
23
55
  """Executes the transformation code on the input and returns the
@@ -33,7 +65,7 @@ async def execute_transformation(code: str) -> str:
33
65
  generated_output_path = code_transformer.export(INPUT_SDIF_PATH)
34
66
 
35
67
  comparisons = []
36
- comparator_kwargs = {}
68
+ comparator_kwargs = {"check_structure_only": True}
37
69
  if SCHEMA_ONLY:
38
70
  comparator_kwargs["check_structure_only"] = True
39
71
 
@@ -53,9 +85,13 @@ async def execute_transformation(code: str) -> str:
53
85
  comparison = comparator.compare(
54
86
  generated_file_path, output_base_file, **comparator_kwargs
55
87
  )
56
- comparisons.append(
57
- f"Comparison for {generated_file_path} [SOURCE] with {output_target_file_name} [TARGET]: {comparison}"
88
+ formatted_message = _format_comparison_output(
89
+ comparison,
90
+ SCHEMA_ONLY,
91
+ generated_file_path,
92
+ output_target_file_name,
58
93
  )
94
+ comparisons.append(formatted_message)
59
95
  else:
60
96
  comparisons.append(
61
97
  f"Error: {output_target_file_name} not found in the generated output"
@@ -69,9 +105,13 @@ async def execute_transformation(code: str) -> str:
69
105
  comparison = comparator.compare(
70
106
  generated_output_path, output_file, **comparator_kwargs
71
107
  )
72
- comparisons.append(
73
- f"Comparison for {generated_output_path} [SOURCE] with {output_target_file_name} [TARGET]: {comparison}"
108
+ formatted_message = _format_comparison_output(
109
+ comparison,
110
+ SCHEMA_ONLY,
111
+ str(generated_output_path),
112
+ output_target_file_name,
74
113
  )
114
+ comparisons.append(formatted_message)
75
115
  else:
76
116
  comparisons.append(
77
117
  "Error: Single output file generated but multiple target files expected"
@@ -112,6 +152,7 @@ class TransformationAsyncCodeBuilder(AsyncCodeBuilder):
112
152
  output_sdif: Optional[Path] = None, # This will now be relative or None
113
153
  instructions: Optional[str] = None,
114
154
  schema_only: bool = False,
155
+ representer_options_for_build: Optional[Dict[str, Any]] = None,
115
156
  ) -> str:
116
157
  global INPUT_SDIF_PATH, OUTPUT_TARGET_FILES, SCHEMA_ONLY
117
158
  # INPUT_SDIF_PATH is used by execute_transformation tool, needs to be accessible from where that tool runs.
@@ -179,16 +220,21 @@ class TransformationAsyncCodeBuilder(AsyncCodeBuilder):
179
220
  else:
180
221
  OUTPUT_TARGET_FILES = {}
181
222
 
182
- output_representation = {}
223
+ output_representation = defaultdict(dict)
183
224
  if OUTPUT_TARGET_FILES:
184
225
  for file_key_abs_path in list(OUTPUT_TARGET_FILES.keys()):
185
226
  agent_facing_name = OUTPUT_TARGET_FILES[file_key_abs_path]
186
- print(f"Representing {agent_facing_name} from {file_key_abs_path}!!")
227
+ print(f"Representing {agent_facing_name} from {file_key_abs_path}")
187
228
  try:
188
229
  # Representer uses the absolute path (file_key_abs_path) to read the example file.
189
- output_representation[agent_facing_name] = get_representer(
190
- file_key_abs_path
191
- ).represent(file_key_abs_path)
230
+ representer = get_representer(file_key_abs_path)
231
+ representation, used_params = representer.represent(
232
+ file_key_abs_path, **(representer_options_for_build or {})
233
+ )
234
+ output_representation[agent_facing_name] = {
235
+ "representation": representation,
236
+ "used_params": used_params,
237
+ }
192
238
  except Exception as e:
193
239
  print(
194
240
  f"Warning: Could not get representation for {agent_facing_name} (path {file_key_abs_path}): {e}"
@@ -213,10 +259,11 @@ class TransformationAsyncCodeBuilder(AsyncCodeBuilder):
213
259
  "output_schema": output_schema_text,
214
260
  "output_sample": output_sample_text
215
261
  if not SCHEMA_ONLY
216
- else "Sample not available. Transform according to the schema only. No data is present in the output example.",
262
+ else "Sample not available.",
217
263
  "output_representation": str(
218
264
  output_representation
219
265
  ), # Representation keyed by agent-facing name
266
+ "instructions": instructions,
220
267
  },
221
268
  )
222
269
  agent = Agent(
File without changes
File without changes
File without changes