qtype 0.0.16__py3-none-any.whl → 0.1.1__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.
- qtype/application/commons/tools.py +1 -1
- qtype/application/converters/tools_from_api.py +5 -5
- qtype/application/converters/tools_from_module.py +2 -2
- qtype/application/converters/types.py +14 -43
- qtype/application/documentation.py +1 -1
- qtype/application/facade.py +94 -73
- qtype/base/types.py +227 -7
- qtype/cli.py +4 -0
- qtype/commands/convert.py +20 -8
- qtype/commands/generate.py +19 -27
- qtype/commands/run.py +73 -36
- qtype/commands/serve.py +74 -54
- qtype/commands/validate.py +34 -8
- qtype/commands/visualize.py +46 -22
- qtype/dsl/__init__.py +6 -5
- qtype/dsl/custom_types.py +1 -1
- qtype/dsl/domain_types.py +65 -5
- qtype/dsl/linker.py +384 -0
- qtype/dsl/loader.py +315 -0
- qtype/dsl/model.py +612 -363
- qtype/dsl/parser.py +200 -0
- qtype/dsl/types.py +50 -0
- qtype/interpreter/api.py +57 -136
- qtype/interpreter/auth/aws.py +19 -9
- qtype/interpreter/auth/generic.py +93 -16
- qtype/interpreter/base/base_step_executor.py +436 -0
- qtype/interpreter/base/batch_step_executor.py +171 -0
- qtype/interpreter/base/exceptions.py +50 -0
- qtype/interpreter/base/executor_context.py +74 -0
- qtype/interpreter/base/factory.py +117 -0
- qtype/interpreter/base/progress_tracker.py +110 -0
- qtype/interpreter/base/secrets.py +339 -0
- qtype/interpreter/base/step_cache.py +74 -0
- qtype/interpreter/base/stream_emitter.py +469 -0
- qtype/interpreter/conversions.py +462 -22
- qtype/interpreter/converters.py +77 -0
- qtype/interpreter/endpoints.py +355 -0
- qtype/interpreter/executors/agent_executor.py +242 -0
- qtype/interpreter/executors/aggregate_executor.py +93 -0
- qtype/interpreter/executors/decoder_executor.py +163 -0
- qtype/interpreter/executors/doc_to_text_executor.py +112 -0
- qtype/interpreter/executors/document_embedder_executor.py +107 -0
- qtype/interpreter/executors/document_search_executor.py +122 -0
- qtype/interpreter/executors/document_source_executor.py +118 -0
- qtype/interpreter/executors/document_splitter_executor.py +105 -0
- qtype/interpreter/executors/echo_executor.py +63 -0
- qtype/interpreter/executors/field_extractor_executor.py +160 -0
- qtype/interpreter/executors/file_source_executor.py +101 -0
- qtype/interpreter/executors/file_writer_executor.py +110 -0
- qtype/interpreter/executors/index_upsert_executor.py +228 -0
- qtype/interpreter/executors/invoke_embedding_executor.py +92 -0
- qtype/interpreter/executors/invoke_flow_executor.py +51 -0
- qtype/interpreter/executors/invoke_tool_executor.py +358 -0
- qtype/interpreter/executors/llm_inference_executor.py +272 -0
- qtype/interpreter/executors/prompt_template_executor.py +78 -0
- qtype/interpreter/executors/sql_source_executor.py +106 -0
- qtype/interpreter/executors/vector_search_executor.py +91 -0
- qtype/interpreter/flow.py +159 -22
- qtype/interpreter/metadata_api.py +115 -0
- qtype/interpreter/resource_cache.py +5 -4
- qtype/interpreter/rich_progress.py +225 -0
- qtype/interpreter/stream/chat/__init__.py +15 -0
- qtype/interpreter/stream/chat/converter.py +391 -0
- qtype/interpreter/{chat → stream/chat}/file_conversions.py +2 -2
- qtype/interpreter/stream/chat/ui_request_to_domain_type.py +140 -0
- qtype/interpreter/stream/chat/vercel.py +609 -0
- qtype/interpreter/stream/utils/__init__.py +15 -0
- qtype/interpreter/stream/utils/build_vercel_ai_formatter.py +74 -0
- qtype/interpreter/stream/utils/callback_to_stream.py +66 -0
- qtype/interpreter/stream/utils/create_streaming_response.py +18 -0
- qtype/interpreter/stream/utils/default_chat_extract_text.py +20 -0
- qtype/interpreter/stream/utils/error_streaming_response.py +20 -0
- qtype/interpreter/telemetry.py +135 -8
- qtype/interpreter/tools/__init__.py +5 -0
- qtype/interpreter/tools/function_tool_helper.py +265 -0
- qtype/interpreter/types.py +330 -0
- qtype/interpreter/typing.py +83 -89
- qtype/interpreter/ui/404/index.html +1 -1
- qtype/interpreter/ui/404.html +1 -1
- qtype/interpreter/ui/_next/static/{nUaw6_IwRwPqkzwe5s725 → 20HoJN6otZ_LyHLHpCPE6}/_buildManifest.js +1 -1
- qtype/interpreter/ui/_next/static/chunks/{393-8fd474427f8e19ce.js → 434-b2112d19f25c44ff.js} +3 -3
- qtype/interpreter/ui/_next/static/chunks/app/page-8c67d16ac90d23cb.js +1 -0
- qtype/interpreter/ui/_next/static/chunks/ba12c10f-546f2714ff8abc66.js +1 -0
- qtype/interpreter/ui/_next/static/css/8a8d1269e362fef7.css +3 -0
- qtype/interpreter/ui/icon.png +0 -0
- qtype/interpreter/ui/index.html +1 -1
- qtype/interpreter/ui/index.txt +4 -4
- qtype/semantic/checker.py +583 -0
- qtype/semantic/generate.py +262 -83
- qtype/semantic/loader.py +95 -0
- qtype/semantic/model.py +436 -159
- qtype/semantic/resolver.py +63 -19
- qtype/semantic/visualize.py +28 -31
- {qtype-0.0.16.dist-info → qtype-0.1.1.dist-info}/METADATA +16 -3
- qtype-0.1.1.dist-info/RECORD +135 -0
- qtype/dsl/base_types.py +0 -38
- qtype/dsl/validator.py +0 -465
- qtype/interpreter/batch/__init__.py +0 -0
- qtype/interpreter/batch/file_sink_source.py +0 -162
- qtype/interpreter/batch/flow.py +0 -95
- qtype/interpreter/batch/sql_source.py +0 -92
- qtype/interpreter/batch/step.py +0 -74
- qtype/interpreter/batch/types.py +0 -41
- qtype/interpreter/batch/utils.py +0 -178
- qtype/interpreter/chat/chat_api.py +0 -237
- qtype/interpreter/chat/vercel.py +0 -314
- qtype/interpreter/exceptions.py +0 -10
- qtype/interpreter/step.py +0 -67
- qtype/interpreter/steps/__init__.py +0 -0
- qtype/interpreter/steps/agent.py +0 -114
- qtype/interpreter/steps/condition.py +0 -36
- qtype/interpreter/steps/decoder.py +0 -88
- qtype/interpreter/steps/llm_inference.py +0 -171
- qtype/interpreter/steps/prompt_template.py +0 -54
- qtype/interpreter/steps/search.py +0 -24
- qtype/interpreter/steps/tool.py +0 -219
- qtype/interpreter/streaming_helpers.py +0 -123
- qtype/interpreter/ui/_next/static/chunks/app/page-7e26b6156cfb55d3.js +0 -1
- qtype/interpreter/ui/_next/static/chunks/ba12c10f-22556063851a6df2.js +0 -1
- qtype/interpreter/ui/_next/static/css/b40532b0db09cce3.css +0 -3
- qtype/interpreter/ui/favicon.ico +0 -0
- qtype/loader.py +0 -390
- qtype-0.0.16.dist-info/RECORD +0 -106
- /qtype/interpreter/ui/_next/static/{nUaw6_IwRwPqkzwe5s725 → 20HoJN6otZ_LyHLHpCPE6}/_ssgManifest.js +0 -0
- {qtype-0.0.16.dist-info → qtype-0.1.1.dist-info}/WHEEL +0 -0
- {qtype-0.0.16.dist-info → qtype-0.1.1.dist-info}/entry_points.txt +0 -0
- {qtype-0.0.16.dist-info → qtype-0.1.1.dist-info}/licenses/LICENSE +0 -0
- {qtype-0.0.16.dist-info → qtype-0.1.1.dist-info}/top_level.txt +0 -0
qtype/dsl/loader.py
ADDED
|
@@ -0,0 +1,315 @@
|
|
|
1
|
+
"""
|
|
2
|
+
YAML loading with environment variable and file inclusion support.
|
|
3
|
+
|
|
4
|
+
This module provides two explicit functions for loading YAML:
|
|
5
|
+
- load_yaml_file(path): Load YAML from a file path or URI
|
|
6
|
+
- load_yaml_string(content, base_path): Load YAML from a string
|
|
7
|
+
|
|
8
|
+
Both support:
|
|
9
|
+
- Environment variable substitution (${VAR} or ${VAR:default})
|
|
10
|
+
- File inclusion (!include and !include_raw)
|
|
11
|
+
- Multiple URI schemes via fsspec (local, http, s3, etc.)
|
|
12
|
+
|
|
13
|
+
Example:
|
|
14
|
+
# Load from file
|
|
15
|
+
data = load_yaml_file("config.yaml")
|
|
16
|
+
data = load_yaml_file("s3://bucket/config.yaml")
|
|
17
|
+
|
|
18
|
+
# Load from string
|
|
19
|
+
yaml_content = "name: test\\nvalue: ${ENV_VAR}"
|
|
20
|
+
data = load_yaml_string(yaml_content)
|
|
21
|
+
|
|
22
|
+
# Load string with includes (requires base_path)
|
|
23
|
+
data = load_yaml_string(yaml_content, base_path="/path/to/configs")
|
|
24
|
+
"""
|
|
25
|
+
|
|
26
|
+
from __future__ import annotations
|
|
27
|
+
|
|
28
|
+
import os
|
|
29
|
+
import re
|
|
30
|
+
from pathlib import Path
|
|
31
|
+
from typing import Any
|
|
32
|
+
|
|
33
|
+
import fsspec
|
|
34
|
+
import yaml
|
|
35
|
+
from dotenv import load_dotenv
|
|
36
|
+
|
|
37
|
+
|
|
38
|
+
class YAMLLoadError(Exception):
|
|
39
|
+
"""Error during YAML loading or parsing."""
|
|
40
|
+
|
|
41
|
+
def __init__(
|
|
42
|
+
self,
|
|
43
|
+
message: str,
|
|
44
|
+
line: int | None = None,
|
|
45
|
+
column: int | None = None,
|
|
46
|
+
source: str | None = None,
|
|
47
|
+
original_error: Exception | None = None,
|
|
48
|
+
) -> None:
|
|
49
|
+
self.message = message
|
|
50
|
+
self.line = line
|
|
51
|
+
self.column = column
|
|
52
|
+
self.source = source
|
|
53
|
+
self.original_error = original_error
|
|
54
|
+
super().__init__(self._format_message())
|
|
55
|
+
|
|
56
|
+
def _format_message(self) -> str:
|
|
57
|
+
"""Format error message with location information."""
|
|
58
|
+
parts = []
|
|
59
|
+
if self.source:
|
|
60
|
+
parts.append(f"in {self.source}")
|
|
61
|
+
if self.line is not None:
|
|
62
|
+
location = f"line {self.line + 1}"
|
|
63
|
+
if self.column is not None:
|
|
64
|
+
location += f", column {self.column + 1}"
|
|
65
|
+
parts.append(location)
|
|
66
|
+
|
|
67
|
+
if parts:
|
|
68
|
+
return f"{self.message} ({', '.join(parts)})"
|
|
69
|
+
return self.message
|
|
70
|
+
|
|
71
|
+
|
|
72
|
+
class YAMLLoader(yaml.SafeLoader):
|
|
73
|
+
"""YAML loader with env var substitution and file inclusion."""
|
|
74
|
+
|
|
75
|
+
def __init__(self, stream: Any, base_path: str | None = None) -> None:
|
|
76
|
+
super().__init__(stream)
|
|
77
|
+
self.base_path = base_path or str(Path.cwd())
|
|
78
|
+
|
|
79
|
+
|
|
80
|
+
def _substitute_env_vars(value: str) -> str:
|
|
81
|
+
"""
|
|
82
|
+
Substitute environment variables in a string.
|
|
83
|
+
|
|
84
|
+
Supports ${VAR_NAME} or ${VAR_NAME:default} syntax.
|
|
85
|
+
|
|
86
|
+
Args:
|
|
87
|
+
value: String containing environment variable references
|
|
88
|
+
|
|
89
|
+
Returns:
|
|
90
|
+
String with environment variables substituted
|
|
91
|
+
|
|
92
|
+
Raises:
|
|
93
|
+
ValueError: If required environment variable is not found
|
|
94
|
+
"""
|
|
95
|
+
pattern = r"\$\{([^}:]+)(?::([^}]*))?\}"
|
|
96
|
+
|
|
97
|
+
def replace_env_var(match: re.Match[str]) -> str:
|
|
98
|
+
var_name = match.group(1)
|
|
99
|
+
default_value = match.group(2)
|
|
100
|
+
|
|
101
|
+
env_value = os.getenv(var_name)
|
|
102
|
+
|
|
103
|
+
if env_value is not None:
|
|
104
|
+
return env_value
|
|
105
|
+
elif default_value is not None:
|
|
106
|
+
return default_value
|
|
107
|
+
else:
|
|
108
|
+
raise ValueError(
|
|
109
|
+
f"Environment variable '{var_name}' is required but not set"
|
|
110
|
+
)
|
|
111
|
+
|
|
112
|
+
return re.sub(pattern, replace_env_var, value)
|
|
113
|
+
|
|
114
|
+
|
|
115
|
+
def _resolve_path(base_path: str, target_path: str) -> str:
|
|
116
|
+
"""
|
|
117
|
+
Resolve a target path relative to base path.
|
|
118
|
+
|
|
119
|
+
Uses fsspec's URL joining logic which handles both local paths and URIs.
|
|
120
|
+
|
|
121
|
+
Args:
|
|
122
|
+
base_path: Base path or URI
|
|
123
|
+
target_path: Target path to resolve (relative or absolute)
|
|
124
|
+
|
|
125
|
+
Returns:
|
|
126
|
+
Resolved absolute path or URI
|
|
127
|
+
"""
|
|
128
|
+
# If target is already absolute (has scheme or starts with /), use as-is
|
|
129
|
+
from urllib.parse import urljoin, urlparse
|
|
130
|
+
|
|
131
|
+
parsed = urlparse(target_path)
|
|
132
|
+
if parsed.scheme or target_path.startswith("/"):
|
|
133
|
+
return target_path
|
|
134
|
+
|
|
135
|
+
# Check if base is URL-like
|
|
136
|
+
base_parsed = urlparse(base_path)
|
|
137
|
+
if base_parsed.scheme:
|
|
138
|
+
# URL-based resolution
|
|
139
|
+
return urljoin(base_path, target_path)
|
|
140
|
+
else:
|
|
141
|
+
# Local file resolution
|
|
142
|
+
base_path_obj = Path(base_path)
|
|
143
|
+
if not base_path_obj.is_dir():
|
|
144
|
+
base_path_obj = base_path_obj.parent
|
|
145
|
+
return str(base_path_obj / target_path)
|
|
146
|
+
|
|
147
|
+
|
|
148
|
+
def _env_var_constructor(loader: YAMLLoader, node: yaml.ScalarNode) -> str:
|
|
149
|
+
"""Constructor for environment variable substitution."""
|
|
150
|
+
value = loader.construct_scalar(node)
|
|
151
|
+
return _substitute_env_vars(value)
|
|
152
|
+
|
|
153
|
+
|
|
154
|
+
def _include_constructor(loader: YAMLLoader, node: yaml.ScalarNode) -> Any:
|
|
155
|
+
"""Constructor for !include tag to load external YAML files."""
|
|
156
|
+
file_path = loader.construct_scalar(node)
|
|
157
|
+
resolved_path = _resolve_path(loader.base_path, file_path)
|
|
158
|
+
|
|
159
|
+
try:
|
|
160
|
+
with fsspec.open(resolved_path, "r", encoding="utf-8") as f:
|
|
161
|
+
content = f.read() # type: ignore[misc]
|
|
162
|
+
# Create a partial function to pass base_path to YAMLLoader
|
|
163
|
+
from functools import partial
|
|
164
|
+
|
|
165
|
+
loader_class = partial(YAMLLoader, base_path=resolved_path)
|
|
166
|
+
return yaml.load(content, loader_class) # type: ignore[arg-type]
|
|
167
|
+
except (FileNotFoundError, IOError, OSError) as e:
|
|
168
|
+
raise FileNotFoundError(
|
|
169
|
+
f"Failed to load included file '{resolved_path}': {e}"
|
|
170
|
+
) from e
|
|
171
|
+
|
|
172
|
+
|
|
173
|
+
def _include_raw_constructor(loader: YAMLLoader, node: yaml.ScalarNode) -> str:
|
|
174
|
+
"""Constructor for !include_raw tag to load external text files."""
|
|
175
|
+
file_path = loader.construct_scalar(node)
|
|
176
|
+
resolved_path = _resolve_path(loader.base_path, file_path)
|
|
177
|
+
|
|
178
|
+
try:
|
|
179
|
+
with fsspec.open(resolved_path, "r", encoding="utf-8") as f:
|
|
180
|
+
return f.read() # type: ignore[no-any-return]
|
|
181
|
+
except (FileNotFoundError, IOError, OSError) as e:
|
|
182
|
+
raise FileNotFoundError(
|
|
183
|
+
f"Failed to load included file '{resolved_path}': {e}"
|
|
184
|
+
) from e
|
|
185
|
+
|
|
186
|
+
|
|
187
|
+
# Register constructors
|
|
188
|
+
YAMLLoader.add_constructor("tag:yaml.org,2002:str", _env_var_constructor)
|
|
189
|
+
YAMLLoader.add_constructor("!include", _include_constructor)
|
|
190
|
+
YAMLLoader.add_constructor("!include_raw", _include_raw_constructor)
|
|
191
|
+
|
|
192
|
+
|
|
193
|
+
def load_yaml_file(path: str | Path) -> dict[str, Any]:
|
|
194
|
+
"""
|
|
195
|
+
Load YAML from a file path or URI.
|
|
196
|
+
|
|
197
|
+
Supports multiple URI schemes via fsspec (local files, http, s3, etc.).
|
|
198
|
+
Automatically loads .env files from the source directory.
|
|
199
|
+
|
|
200
|
+
Args:
|
|
201
|
+
path: File path or URI to load
|
|
202
|
+
|
|
203
|
+
Returns:
|
|
204
|
+
Parsed YAML as dictionary
|
|
205
|
+
|
|
206
|
+
Raises:
|
|
207
|
+
YAMLLoadError: If YAML parsing fails
|
|
208
|
+
FileNotFoundError: If file doesn't exist
|
|
209
|
+
ValueError: If required environment variable is missing
|
|
210
|
+
"""
|
|
211
|
+
source_str = str(path)
|
|
212
|
+
|
|
213
|
+
# Load .env file if it exists in the source directory
|
|
214
|
+
try:
|
|
215
|
+
from urllib.parse import urlparse
|
|
216
|
+
|
|
217
|
+
parsed = urlparse(source_str)
|
|
218
|
+
if parsed.scheme in ["file", ""]:
|
|
219
|
+
# Local file - load .env from same directory
|
|
220
|
+
source_path = Path(parsed.path if parsed.path else source_str)
|
|
221
|
+
if source_path.is_file():
|
|
222
|
+
env_dir = source_path.parent
|
|
223
|
+
env_file = env_dir / ".env"
|
|
224
|
+
if env_file.exists():
|
|
225
|
+
load_dotenv(env_file)
|
|
226
|
+
except Exception:
|
|
227
|
+
pass
|
|
228
|
+
|
|
229
|
+
# Also try cwd
|
|
230
|
+
load_dotenv()
|
|
231
|
+
|
|
232
|
+
# Load file content
|
|
233
|
+
try:
|
|
234
|
+
with fsspec.open(source_str, "r", encoding="utf-8") as f:
|
|
235
|
+
content = f.read() # type: ignore[misc]
|
|
236
|
+
except FileNotFoundError as e:
|
|
237
|
+
raise FileNotFoundError(f"File not found: {source_str}") from e
|
|
238
|
+
|
|
239
|
+
return _parse_yaml(content, base_path=source_str, source_name=source_str)
|
|
240
|
+
|
|
241
|
+
|
|
242
|
+
def load_yaml_string(
|
|
243
|
+
content: str, base_path: str | Path | None = None
|
|
244
|
+
) -> dict[str, Any]:
|
|
245
|
+
"""
|
|
246
|
+
Load YAML from a string.
|
|
247
|
+
|
|
248
|
+
Args:
|
|
249
|
+
content: Raw YAML content as string
|
|
250
|
+
base_path: Base path for resolving relative includes (default: cwd)
|
|
251
|
+
|
|
252
|
+
Returns:
|
|
253
|
+
Parsed YAML as dictionary
|
|
254
|
+
|
|
255
|
+
Raises:
|
|
256
|
+
YAMLLoadError: If YAML parsing fails
|
|
257
|
+
ValueError: If required environment variable is missing
|
|
258
|
+
"""
|
|
259
|
+
load_dotenv()
|
|
260
|
+
|
|
261
|
+
base = str(base_path) if base_path else str(Path.cwd())
|
|
262
|
+
return _parse_yaml(content, base_path=base, source_name="<string>")
|
|
263
|
+
|
|
264
|
+
|
|
265
|
+
def _parse_yaml(
|
|
266
|
+
content: str, base_path: str, source_name: str
|
|
267
|
+
) -> dict[str, Any]:
|
|
268
|
+
"""
|
|
269
|
+
Parse YAML content with environment variable substitution and includes.
|
|
270
|
+
|
|
271
|
+
Args:
|
|
272
|
+
content: YAML content to parse
|
|
273
|
+
base_path: Base path for resolving relative includes
|
|
274
|
+
source_name: Source name for error messages
|
|
275
|
+
|
|
276
|
+
Returns:
|
|
277
|
+
Parsed YAML as dictionary
|
|
278
|
+
|
|
279
|
+
Raises:
|
|
280
|
+
YAMLLoadError: If YAML parsing fails
|
|
281
|
+
"""
|
|
282
|
+
try:
|
|
283
|
+
from functools import partial
|
|
284
|
+
|
|
285
|
+
loader_class = partial(YAMLLoader, base_path=base_path)
|
|
286
|
+
result = yaml.load(content, loader_class) # type: ignore[arg-type]
|
|
287
|
+
return result # type: ignore[no-any-return]
|
|
288
|
+
except yaml.YAMLError as e:
|
|
289
|
+
# Extract line/column information if available
|
|
290
|
+
line = None
|
|
291
|
+
column = None
|
|
292
|
+
|
|
293
|
+
if hasattr(e, "problem_mark") and e.problem_mark: # type: ignore[attr-defined]
|
|
294
|
+
line = e.problem_mark.line # type: ignore[attr-defined]
|
|
295
|
+
column = e.problem_mark.column # type: ignore[attr-defined]
|
|
296
|
+
|
|
297
|
+
# Format error message
|
|
298
|
+
error_msg = str(e)
|
|
299
|
+
if hasattr(e, "problem"):
|
|
300
|
+
error_msg = e.problem or error_msg # type: ignore[attr-defined]
|
|
301
|
+
|
|
302
|
+
raise YAMLLoadError(
|
|
303
|
+
message=f"YAML parsing error: {error_msg}",
|
|
304
|
+
line=line,
|
|
305
|
+
column=column,
|
|
306
|
+
source=source_name,
|
|
307
|
+
original_error=e,
|
|
308
|
+
) from e
|
|
309
|
+
except ValueError as e:
|
|
310
|
+
# Environment variable errors
|
|
311
|
+
raise YAMLLoadError(
|
|
312
|
+
message=str(e),
|
|
313
|
+
source=source_name,
|
|
314
|
+
original_error=e,
|
|
315
|
+
) from e
|