satif-ai 0.2.2__py3-none-any.whl → 0.2.4__py3-none-any.whl

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,10 +1,11 @@
1
+ import base64
1
2
  import os
2
3
  import re
3
4
  from pathlib import Path
4
5
  from typing import Dict, List, Optional, Union
5
6
 
6
7
  from agents import Agent, Runner, function_tool
7
- from agents.mcp.server import MCPServerStdio
8
+ from agents.mcp.server import MCPServer
8
9
  from mcp import ClientSession
9
10
  from satif_core import AsyncCodeBuilder, CodeBuilder, SDIFDatabase
10
11
  from satif_sdk.comparators import get_comparator
@@ -88,7 +89,7 @@ class TransformationAsyncCodeBuilder(AsyncCodeBuilder):
88
89
 
89
90
  def __init__(
90
91
  self,
91
- mcp_server: MCPServerStdio,
92
+ mcp_server: MCPServer,
92
93
  mcp_session: ClientSession,
93
94
  llm_model: str = "o3-mini",
94
95
  ):
@@ -98,39 +99,115 @@ class TransformationAsyncCodeBuilder(AsyncCodeBuilder):
98
99
 
99
100
  async def build(
100
101
  self,
101
- sdif: Path,
102
+ sdif: Path, # This will now be relative to project root (MCP server CWD)
102
103
  output_target_files: Dict[Union[str, Path], str] | List[Path],
103
- output_sdif: Optional[Path] = None,
104
+ output_sdif: Optional[Path] = None, # This will now be relative or None
104
105
  instructions: Optional[str] = None,
105
106
  ) -> str:
106
107
  global INPUT_SDIF_PATH, OUTPUT_TARGET_FILES
107
- INPUT_SDIF_PATH = Path(sdif)
108
+ # INPUT_SDIF_PATH is used by execute_transformation tool, needs to be accessible from where that tool runs.
109
+ # If execute_transformation runs in the same process as the builder, absolute path is fine.
110
+ # If it were a separate context, this might need adjustment.
111
+ # For now, assume execute_transformation can access absolute paths if needed for its *input SDIF*.
112
+ # However, the sdif for MCP URIs must be relative.
113
+ INPUT_SDIF_PATH = Path(
114
+ sdif
115
+ ).resolve() # Keep this as absolute for the tool's potential direct access.
116
+
117
+ # Paths for MCP URIs are now expected to be relative to MCP server CWD (project root)
118
+ # So, use them directly as strings.
119
+ input_sdif_mcp_uri_path = base64.b64encode(str(sdif).encode()).decode()
120
+ output_sdif_mcp_uri_path = (
121
+ base64.b64encode(str(output_sdif).encode()).decode()
122
+ if output_sdif
123
+ else None
124
+ )
108
125
 
109
- if isinstance(output_target_files, list):
110
- OUTPUT_TARGET_FILES = {file: file.name for file in output_target_files}
111
- else:
112
- OUTPUT_TARGET_FILES = output_target_files
126
+ input_schema = await self.mcp_session.read_resource(
127
+ f"schema://{input_sdif_mcp_uri_path}"
128
+ )
129
+ input_sample = await self.mcp_session.read_resource(
130
+ f"sample://{input_sdif_mcp_uri_path}"
131
+ )
132
+
133
+ output_schema_text = "N/A"
134
+ output_sample_text = "N/A"
135
+ if output_sdif_mcp_uri_path:
136
+ try:
137
+ output_schema_content = await self.mcp_session.read_resource(
138
+ f"schema://{output_sdif_mcp_uri_path}"
139
+ )
140
+ if output_schema_content.contents:
141
+ output_schema_text = output_schema_content.contents[0].text
142
+ except Exception as e:
143
+ print(
144
+ f"Warning: Could not read schema for output_sdif {output_sdif_mcp_uri_path}: {e}"
145
+ )
113
146
 
114
- input_schema = await self.mcp_session.read_resource(f"schema://{sdif}")
115
- input_sample = await self.mcp_session.read_resource(f"sample://{sdif}")
147
+ try:
148
+ output_sample_content = await self.mcp_session.read_resource(
149
+ f"sample://{output_sdif_mcp_uri_path}"
150
+ )
151
+ if output_sample_content.contents:
152
+ output_sample_text = output_sample_content.contents[0].text
153
+ except Exception as e:
154
+ print(
155
+ f"Warning: Could not read sample for output_sdif {output_sdif_mcp_uri_path}: {e}"
156
+ )
116
157
 
117
- output_schema = await self.mcp_session.read_resource(f"schema://{output_sdif}")
118
- output_sample = await self.mcp_session.read_resource(f"sample://{output_sdif}")
119
- output_representation = {
120
- file: get_representer(file).represent(file)
121
- for file in list(OUTPUT_TARGET_FILES.keys())
122
- }
158
+ # OUTPUT_TARGET_FILES keys are absolute paths to original example files for local reading by representers/comparators.
159
+ # Values are agent-facing filenames.
160
+ if isinstance(output_target_files, list):
161
+ OUTPUT_TARGET_FILES = {
162
+ file_path.resolve(): file_path.name for file_path in output_target_files
163
+ }
164
+ elif isinstance(output_target_files, dict):
165
+ temp_map = {}
166
+ for k, v in output_target_files.items():
167
+ if isinstance(k, Path):
168
+ temp_map[k.resolve()] = v
169
+ else:
170
+ temp_map[k] = v
171
+ OUTPUT_TARGET_FILES = temp_map
172
+ else:
173
+ OUTPUT_TARGET_FILES = {}
174
+
175
+ output_representation = {}
176
+ if OUTPUT_TARGET_FILES:
177
+ for file_key_abs_path in list(OUTPUT_TARGET_FILES.keys()):
178
+ agent_facing_name = OUTPUT_TARGET_FILES[file_key_abs_path]
179
+ print(f"Representing {agent_facing_name} from {file_key_abs_path}!!")
180
+ try:
181
+ # Representer uses the absolute path (file_key_abs_path) to read the example file.
182
+ output_representation[agent_facing_name] = get_representer(
183
+ file_key_abs_path
184
+ ).represent(file_key_abs_path)
185
+ except Exception as e:
186
+ print(
187
+ f"Warning: Could not get representation for {agent_facing_name} (path {file_key_abs_path}): {e}"
188
+ )
189
+ output_representation[agent_facing_name] = (
190
+ f"Error representing file: {e}"
191
+ )
123
192
 
124
193
  prompt = await self.mcp_session.get_prompt(
125
194
  "create_transformation",
126
195
  arguments={
127
- "input_file": INPUT_SDIF_PATH.name,
128
- "input_schema": input_schema.contents[0].text,
129
- "input_sample": input_sample.contents[0].text,
196
+ "input_file": Path(
197
+ input_sdif_mcp_uri_path
198
+ ).name, # Display name for prompt (from relative path)
199
+ "input_schema": input_schema.contents[0].text
200
+ if input_schema.contents
201
+ else "Error reading input schema",
202
+ "input_sample": input_sample.contents[0].text
203
+ if input_sample.contents
204
+ else "Error reading input sample",
130
205
  "output_files": str(list(OUTPUT_TARGET_FILES.values())),
131
- "output_schema": output_schema.contents[0].text,
132
- "output_sample": output_sample.contents[0].text,
133
- "output_representation": str(output_representation),
206
+ "output_schema": output_schema_text,
207
+ "output_sample": output_sample_text,
208
+ "output_representation": str(
209
+ output_representation
210
+ ), # Representation keyed by agent-facing name
134
211
  },
135
212
  )
136
213
  agent = Agent(
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.3
2
2
  Name: satif-ai
3
- Version: 0.2.2
3
+ Version: 0.2.4
4
4
  Summary: AI Agents for Satif
5
5
  License: MIT
6
6
  Author: Bryan Djafer
@@ -3,15 +3,15 @@ satif_ai/adapters/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU
3
3
  satif_ai/adapters/tidy.py,sha256=2oYj7Gz3vOQtzcpoJI4JbftWlMKvOWL8rdwthjg-zUE,19884
4
4
  satif_ai/code_builders/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
5
5
  satif_ai/code_builders/adaptation.py,sha256=E29YM0S6pMtAfB0uzSUexoeWKwXfF8iJVyYUCKWQz5k,188
6
- satif_ai/code_builders/transformation.py,sha256=fdegXe2jNYxbPWOoDKhpKws8ltO5we-aJQQAhBBYVWQ,5970
6
+ satif_ai/code_builders/transformation.py,sha256=c0-7JTs5pgiDOYxjWtB-w8Z-nwwqDWSUPCY1kJo3xEs,9638
7
7
  satif_ai/plot_builders/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
8
8
  satif_ai/plot_builders/agent.py,sha256=Ncw7SL9qkpRN0hw76ezSo1K8vVQK6gcXFp8x8VFwqUI,8291
9
9
  satif_ai/plot_builders/prompt.py,sha256=m0W1SsxnB9_FhIYRumkthImJbK-7KUm4dygN3kjAXGk,6877
10
10
  satif_ai/plot_builders/tool.py,sha256=MeLnG_wFoITSVWZcNFsQLCi157O4L3wItQgolBa4fAw,5994
11
11
  satif_ai/standardizers/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
12
12
  satif_ai/standardizers/ai_csv.py,sha256=AAeTt7eqFAtayxF2b95Z_K_lnMdwBBnv2Cn-qTEpMp8,29499
13
- satif_ai-0.2.2.dist-info/LICENSE,sha256=kS8EN6yAaGZd7V5z6GKSn_x3ozcZltrfRky4vMPRCw8,1072
14
- satif_ai-0.2.2.dist-info/METADATA,sha256=1Ogdh-FlKqAL-BIe2fguZatQQAQVTLmw0Ume2s41FKU,670
15
- satif_ai-0.2.2.dist-info/WHEEL,sha256=b4K_helf-jlQoXBBETfwnf4B04YC67LOev0jo4fX5m8,88
16
- satif_ai-0.2.2.dist-info/entry_points.txt,sha256=_8RP7sSos2cwqYblhwHOK3hhRkLbP6XkbAju3vHWft8,40
17
- satif_ai-0.2.2.dist-info/RECORD,,
13
+ satif_ai-0.2.4.dist-info/LICENSE,sha256=kS8EN6yAaGZd7V5z6GKSn_x3ozcZltrfRky4vMPRCw8,1072
14
+ satif_ai-0.2.4.dist-info/METADATA,sha256=3wCHxt5KwmSGllAwhqSQus7rgtcbteW7DYPmKRxIO-A,670
15
+ satif_ai-0.2.4.dist-info/WHEEL,sha256=b4K_helf-jlQoXBBETfwnf4B04YC67LOev0jo4fX5m8,88
16
+ satif_ai-0.2.4.dist-info/entry_points.txt,sha256=Mz2SwYALjktap1bF-Q3EWBgiZVNT6QJCVsCs_fCV33Y,43
17
+ satif_ai-0.2.4.dist-info/RECORD,,
@@ -0,0 +1,3 @@
1
+ [console_scripts]
2
+ satif-ai=satif.cli:main
3
+
@@ -1,3 +0,0 @@
1
- [console_scripts]
2
- satif=satif.cli:main
3
-