qtype 0.0.11__py3-none-any.whl → 0.0.13__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/converters/tools_from_api.py +476 -11
- qtype/application/converters/tools_from_module.py +37 -13
- qtype/application/converters/types.py +17 -3
- qtype/application/facade.py +17 -20
- qtype/commands/convert.py +36 -2
- qtype/commands/generate.py +48 -0
- qtype/commands/run.py +1 -0
- qtype/commands/serve.py +11 -1
- qtype/commands/validate.py +8 -11
- qtype/commands/visualize.py +0 -3
- qtype/dsl/model.py +190 -4
- qtype/dsl/validator.py +2 -1
- qtype/interpreter/api.py +5 -1
- qtype/interpreter/batch/file_sink_source.py +162 -0
- qtype/interpreter/batch/flow.py +1 -1
- qtype/interpreter/batch/sql_source.py +3 -6
- qtype/interpreter/batch/step.py +12 -1
- qtype/interpreter/batch/utils.py +8 -9
- qtype/interpreter/step.py +2 -2
- qtype/interpreter/steps/tool.py +194 -28
- qtype/interpreter/ui/404/index.html +1 -1
- qtype/interpreter/ui/404.html +1 -1
- qtype/interpreter/ui/_next/static/chunks/393-8fd474427f8e19ce.js +36 -0
- qtype/interpreter/ui/_next/static/chunks/{964-ed4ab073db645007.js → 964-2b041321a01cbf56.js} +1 -1
- qtype/interpreter/ui/_next/static/chunks/app/{layout-5ccbc44fd528d089.js → layout-a05273ead5de2c41.js} +1 -1
- qtype/interpreter/ui/_next/static/chunks/app/page-7e26b6156cfb55d3.js +1 -0
- qtype/interpreter/ui/_next/static/chunks/{main-6d261b6c5d6fb6c2.js → main-e26b9cb206da2cac.js} +1 -1
- qtype/interpreter/ui/_next/static/chunks/webpack-08642e441b39b6c2.js +1 -0
- qtype/interpreter/ui/_next/static/css/b40532b0db09cce3.css +3 -0
- qtype/interpreter/ui/_next/static/media/4cf2300e9c8272f7-s.p.woff2 +0 -0
- qtype/interpreter/ui/index.html +1 -1
- qtype/interpreter/ui/index.txt +4 -4
- qtype/loader.py +8 -2
- qtype/semantic/generate.py +6 -2
- qtype/semantic/model.py +132 -77
- qtype/semantic/visualize.py +24 -6
- {qtype-0.0.11.dist-info → qtype-0.0.13.dist-info}/METADATA +4 -2
- {qtype-0.0.11.dist-info → qtype-0.0.13.dist-info}/RECORD +44 -43
- qtype/interpreter/ui/_next/static/chunks/736-7fc606e244fedcb1.js +0 -36
- qtype/interpreter/ui/_next/static/chunks/app/page-c72e847e888e549d.js +0 -1
- qtype/interpreter/ui/_next/static/chunks/webpack-8289c17c67827f22.js +0 -1
- qtype/interpreter/ui/_next/static/css/a262c53826df929b.css +0 -3
- qtype/interpreter/ui/_next/static/media/569ce4b8f30dc480-s.p.woff2 +0 -0
- /qtype/interpreter/ui/_next/static/{OT8QJQW3J70VbDWWfrEMT → nUaw6_IwRwPqkzwe5s725}/_buildManifest.js +0 -0
- /qtype/interpreter/ui/_next/static/{OT8QJQW3J70VbDWWfrEMT → nUaw6_IwRwPqkzwe5s725}/_ssgManifest.js +0 -0
- {qtype-0.0.11.dist-info → qtype-0.0.13.dist-info}/WHEEL +0 -0
- {qtype-0.0.11.dist-info → qtype-0.0.13.dist-info}/entry_points.txt +0 -0
- {qtype-0.0.11.dist-info → qtype-0.0.13.dist-info}/licenses/LICENSE +0 -0
- {qtype-0.0.11.dist-info → qtype-0.0.13.dist-info}/top_level.txt +0 -0
qtype/interpreter/batch/flow.py
CHANGED
|
@@ -52,7 +52,7 @@ def batch_execute_flow(
|
|
|
52
52
|
batch_size = batch_config.batch_size
|
|
53
53
|
for start in range(0, len(previous_outputs), batch_size):
|
|
54
54
|
end = start + batch_size
|
|
55
|
-
batch = previous_outputs.iloc[start:end]
|
|
55
|
+
batch = previous_outputs.iloc[start:end].copy()
|
|
56
56
|
# Execute the step with the current batch
|
|
57
57
|
batch_results, batch_errors = batch_execute_step(
|
|
58
58
|
step, batch, batch_config
|
|
@@ -9,10 +9,7 @@ from sqlalchemy.exc import SQLAlchemyError
|
|
|
9
9
|
from qtype.base.exceptions import InterpreterError
|
|
10
10
|
from qtype.interpreter.auth.generic import auth
|
|
11
11
|
from qtype.interpreter.batch.types import BatchConfig, ErrorMode
|
|
12
|
-
from qtype.interpreter.batch.utils import
|
|
13
|
-
reconcile_results_and_errors,
|
|
14
|
-
validate_inputs,
|
|
15
|
-
)
|
|
12
|
+
from qtype.interpreter.batch.utils import reconcile_results_and_errors
|
|
16
13
|
from qtype.semantic.model import SQLSource
|
|
17
14
|
|
|
18
15
|
|
|
@@ -56,8 +53,6 @@ def execute_sql_source(
|
|
|
56
53
|
- The second DataFrame contains rows that encountered errors with an 'error' column.
|
|
57
54
|
"""
|
|
58
55
|
# Create a database engine
|
|
59
|
-
validate_inputs(inputs, step)
|
|
60
|
-
|
|
61
56
|
connect_args = {}
|
|
62
57
|
if step.auth:
|
|
63
58
|
with auth(step.auth) as creds:
|
|
@@ -84,6 +79,8 @@ def execute_sql_source(
|
|
|
84
79
|
result.fetchall(), columns=list(result.keys())
|
|
85
80
|
)
|
|
86
81
|
df = to_output_columns(df, output_columns)
|
|
82
|
+
# Augment with all input row columns (fan-out-right)
|
|
83
|
+
df = df.assign(**row.to_dict())
|
|
87
84
|
results.append(df)
|
|
88
85
|
except SQLAlchemyError as e:
|
|
89
86
|
if batch_config.error_mode == ErrorMode.FAIL:
|
qtype/interpreter/batch/step.py
CHANGED
|
@@ -3,6 +3,10 @@ from typing import Any, Tuple
|
|
|
3
3
|
|
|
4
4
|
import pandas as pd
|
|
5
5
|
|
|
6
|
+
from qtype.interpreter.batch.file_sink_source import (
|
|
7
|
+
execute_file_sink,
|
|
8
|
+
execute_file_source,
|
|
9
|
+
)
|
|
6
10
|
from qtype.interpreter.batch.sql_source import execute_sql_source
|
|
7
11
|
from qtype.interpreter.batch.types import BatchConfig
|
|
8
12
|
from qtype.interpreter.batch.utils import (
|
|
@@ -14,6 +18,8 @@ from qtype.interpreter.exceptions import InterpreterError
|
|
|
14
18
|
from qtype.semantic.model import (
|
|
15
19
|
Condition,
|
|
16
20
|
Decoder,
|
|
21
|
+
FileSink,
|
|
22
|
+
FileSource,
|
|
17
23
|
Flow,
|
|
18
24
|
PromptTemplate,
|
|
19
25
|
Search,
|
|
@@ -44,6 +50,7 @@ def batch_execute_step(
|
|
|
44
50
|
Tuple[pd.DataFrame, pd.DataFrame]: A tuple containing the output results and any rows that returned errors.
|
|
45
51
|
"""
|
|
46
52
|
|
|
53
|
+
# ensure the inputs to step are included in the current data frame
|
|
47
54
|
validate_inputs(inputs, step)
|
|
48
55
|
|
|
49
56
|
if isinstance(step, Flow):
|
|
@@ -52,7 +59,11 @@ def batch_execute_step(
|
|
|
52
59
|
return batch_execute_flow(step, inputs, batch_config, **kwargs)
|
|
53
60
|
elif isinstance(step, SQLSource):
|
|
54
61
|
return execute_sql_source(step, inputs, batch_config, **kwargs)
|
|
55
|
-
elif step
|
|
62
|
+
elif isinstance(step, FileSource):
|
|
63
|
+
return execute_file_source(step, inputs, batch_config, **kwargs)
|
|
64
|
+
elif isinstance(step, FileSink):
|
|
65
|
+
return execute_file_sink(step, inputs, batch_config, **kwargs)
|
|
66
|
+
elif type(step) in SINGLE_WRAP_STEPS:
|
|
56
67
|
return batch_iterator(
|
|
57
68
|
f=partial(single_step_adapter, step=step),
|
|
58
69
|
batch=inputs,
|
qtype/interpreter/batch/utils.py
CHANGED
|
@@ -15,19 +15,15 @@ class InputMissingError(Exception):
|
|
|
15
15
|
pass
|
|
16
16
|
|
|
17
17
|
|
|
18
|
-
def validate_inputs(batch: pd.DataFrame, step: Step) ->
|
|
18
|
+
def validate_inputs(batch: pd.DataFrame, step: Step) -> None:
|
|
19
19
|
"""Ensures all input variables for the step are columns in the DataFrame.
|
|
20
20
|
If not, an Exception is raised.
|
|
21
21
|
|
|
22
22
|
Args:
|
|
23
23
|
batch: The input DataFrame to decode.
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
Returns:
|
|
27
|
-
A view of the dataframe with only the input columns for the step.
|
|
28
|
-
|
|
24
|
+
step: The step to validate.
|
|
29
25
|
Raises:
|
|
30
|
-
InputMissingError: If
|
|
26
|
+
InputMissingError: If any input variable is missing from the DataFrame.
|
|
31
27
|
"""
|
|
32
28
|
input_ids = [input_var.id for input_var in step.inputs]
|
|
33
29
|
for input_var in input_ids:
|
|
@@ -35,7 +31,6 @@ def validate_inputs(batch: pd.DataFrame, step: Step) -> pd.DataFrame:
|
|
|
35
31
|
raise InputMissingError(
|
|
36
32
|
f"Input DataFrame must contain column '{input_var}' for step {step.id}."
|
|
37
33
|
)
|
|
38
|
-
return batch[input_ids]
|
|
39
34
|
|
|
40
35
|
|
|
41
36
|
def fail_mode_wrapper(
|
|
@@ -58,7 +53,7 @@ def fail_mode_wrapper(
|
|
|
58
53
|
try:
|
|
59
54
|
# turn row into a dict and merge with kwargs
|
|
60
55
|
merged_kwargs = {**row.to_dict(), **kwargs}
|
|
61
|
-
return f(**merged_kwargs)
|
|
56
|
+
return {**f(**merged_kwargs), **row.to_dict()}
|
|
62
57
|
except Exception as e:
|
|
63
58
|
if batch_config.error_mode == ErrorMode.FAIL:
|
|
64
59
|
raise e
|
|
@@ -132,6 +127,10 @@ def batch_iterator(
|
|
|
132
127
|
|
|
133
128
|
results = batch.apply(the_pipe, axis=1)
|
|
134
129
|
|
|
130
|
+
# If error column doesn't exist, add it with NaN values
|
|
131
|
+
if error_col not in results.columns:
|
|
132
|
+
results[error_col] = pd.NA
|
|
133
|
+
|
|
135
134
|
# Split the results into two dataframes, one where error_col is not defined, and one where it is.
|
|
136
135
|
success_mask = ~results[error_col].notna()
|
|
137
136
|
failed_mask = results[error_col].notna()
|
qtype/interpreter/step.py
CHANGED
|
@@ -18,11 +18,11 @@ from qtype.semantic.model import (
|
|
|
18
18
|
Condition,
|
|
19
19
|
Decoder,
|
|
20
20
|
Flow,
|
|
21
|
+
Invoke,
|
|
21
22
|
LLMInference,
|
|
22
23
|
PromptTemplate,
|
|
23
24
|
Search,
|
|
24
25
|
Step,
|
|
25
|
-
Tool,
|
|
26
26
|
Variable,
|
|
27
27
|
)
|
|
28
28
|
|
|
@@ -60,7 +60,7 @@ def execute_step(step: Step, **kwargs: dict[str, Any]) -> list[Variable]:
|
|
|
60
60
|
return prompt_template.execute(step, **kwargs) # type: ignore[arg-type]
|
|
61
61
|
elif isinstance(step, Search):
|
|
62
62
|
return search.execute(step, **kwargs) # type: ignore[arg-type]
|
|
63
|
-
elif isinstance(step,
|
|
63
|
+
elif isinstance(step, Invoke):
|
|
64
64
|
return tool.execute(step, **kwargs) # type: ignore[arg-type]
|
|
65
65
|
else:
|
|
66
66
|
# Handle other step types if necessary
|
qtype/interpreter/steps/tool.py
CHANGED
|
@@ -1,53 +1,219 @@
|
|
|
1
1
|
import importlib
|
|
2
2
|
import logging
|
|
3
|
+
import time
|
|
4
|
+
from typing import Any, Callable
|
|
5
|
+
|
|
6
|
+
import requests
|
|
7
|
+
from pydantic import BaseModel
|
|
3
8
|
|
|
4
9
|
from qtype.interpreter.exceptions import InterpreterError
|
|
5
|
-
from qtype.semantic.model import
|
|
10
|
+
from qtype.semantic.model import (
|
|
11
|
+
APITool,
|
|
12
|
+
BearerTokenAuthProvider,
|
|
13
|
+
Invoke,
|
|
14
|
+
PythonFunctionTool,
|
|
15
|
+
Variable,
|
|
16
|
+
)
|
|
6
17
|
|
|
7
18
|
logger = logging.getLogger(__name__)
|
|
8
19
|
|
|
9
20
|
|
|
10
|
-
def
|
|
11
|
-
|
|
21
|
+
def _execute_function_tool(
|
|
22
|
+
tool: PythonFunctionTool, inputs: dict[str, Any]
|
|
23
|
+
) -> Any:
|
|
24
|
+
"""Execute a Python function tool.
|
|
12
25
|
|
|
13
26
|
Args:
|
|
14
|
-
tool: The tool
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
27
|
+
tool: The Python function tool to execute.
|
|
28
|
+
inputs: Dictionary of input parameter names to values.
|
|
29
|
+
|
|
30
|
+
Returns:
|
|
31
|
+
The result from the function call.
|
|
18
32
|
|
|
19
|
-
|
|
20
|
-
|
|
33
|
+
Raises:
|
|
34
|
+
InterpreterError: If the function cannot be found or executed.
|
|
35
|
+
"""
|
|
36
|
+
try:
|
|
21
37
|
module = importlib.import_module(tool.module_path)
|
|
22
38
|
function = getattr(module, tool.function_name, None)
|
|
23
39
|
if function is None:
|
|
24
40
|
raise InterpreterError(
|
|
25
41
|
f"Function {tool.function_name} not found in {tool.module_path}"
|
|
26
42
|
)
|
|
27
|
-
|
|
28
|
-
|
|
43
|
+
return function(**inputs)
|
|
44
|
+
except Exception as e:
|
|
45
|
+
raise InterpreterError(
|
|
46
|
+
f"Failed to execute function {tool.function_name}: {e}"
|
|
47
|
+
) from e
|
|
48
|
+
|
|
49
|
+
|
|
50
|
+
def _execute_api_tool(
|
|
51
|
+
tool: APITool, inputs: dict[str, Any], stream_fn: Callable | None = None
|
|
52
|
+
) -> Any:
|
|
53
|
+
"""Execute an API tool by making an HTTP request.
|
|
54
|
+
|
|
55
|
+
Args:
|
|
56
|
+
tool: The API tool to execute.
|
|
57
|
+
inputs: Dictionary of input parameter names to values.
|
|
58
|
+
|
|
59
|
+
Returns:
|
|
60
|
+
The result from the API call.
|
|
61
|
+
|
|
62
|
+
Raises:
|
|
63
|
+
InterpreterError: If the auth provider is not supported or the request fails.
|
|
64
|
+
"""
|
|
65
|
+
# Prepare headers
|
|
66
|
+
headers = tool.headers.copy() if tool.headers else {}
|
|
67
|
+
|
|
68
|
+
# Handle authentication
|
|
69
|
+
if tool.auth is not None:
|
|
70
|
+
if isinstance(tool.auth, BearerTokenAuthProvider):
|
|
71
|
+
headers["Authorization"] = f"Bearer {tool.auth.token}"
|
|
72
|
+
else:
|
|
29
73
|
raise InterpreterError(
|
|
30
|
-
f"
|
|
74
|
+
f"Unsupported auth provider type: {type(tool.auth).__name__}. "
|
|
75
|
+
"Only BearerTokenAuthProvider is currently supported."
|
|
31
76
|
)
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
#
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
77
|
+
|
|
78
|
+
# Prepare request body
|
|
79
|
+
def dump_if_necessary(value: Any) -> Any:
|
|
80
|
+
# if value is a dictionary, call recursively
|
|
81
|
+
if isinstance(value, dict):
|
|
82
|
+
return {k: dump_if_necessary(v) for k, v in value.items()}
|
|
83
|
+
elif isinstance(value, BaseModel):
|
|
84
|
+
return value.model_dump()
|
|
85
|
+
return value
|
|
86
|
+
|
|
87
|
+
# Use inputs for request body
|
|
88
|
+
body = None
|
|
89
|
+
if inputs:
|
|
90
|
+
body = dump_if_necessary(inputs)
|
|
91
|
+
|
|
92
|
+
try:
|
|
93
|
+
if stream_fn:
|
|
94
|
+
stream_fn(f"Making request to {tool.endpoint}...")
|
|
95
|
+
|
|
96
|
+
logging.info(f"Making request to {tool.endpoint}")
|
|
97
|
+
# Record start time
|
|
98
|
+
start_time = time.time()
|
|
99
|
+
|
|
100
|
+
# Make the HTTP request
|
|
101
|
+
response = requests.request(
|
|
102
|
+
method=tool.method.upper(),
|
|
103
|
+
url=tool.endpoint,
|
|
104
|
+
headers=headers,
|
|
105
|
+
params=None
|
|
106
|
+
if tool.method.upper() in ["POST", "PUT", "PATCH"]
|
|
107
|
+
else inputs,
|
|
108
|
+
json=body
|
|
109
|
+
if tool.method.upper() in ["POST", "PUT", "PATCH"]
|
|
110
|
+
else None,
|
|
111
|
+
)
|
|
112
|
+
|
|
113
|
+
# Calculate and log request duration
|
|
114
|
+
duration = time.time() - start_time
|
|
115
|
+
if stream_fn:
|
|
116
|
+
stream_fn(
|
|
117
|
+
f"Request to {tool.endpoint} completed in {duration:.2f} seconds"
|
|
118
|
+
)
|
|
119
|
+
logging.info(
|
|
120
|
+
f"Request to {tool.endpoint} completed in {duration:.2f} seconds"
|
|
121
|
+
)
|
|
122
|
+
|
|
123
|
+
# Raise an exception for HTTP error status codes
|
|
124
|
+
response.raise_for_status()
|
|
125
|
+
|
|
126
|
+
# Return the decoded JSON response
|
|
127
|
+
return response.json()
|
|
128
|
+
|
|
129
|
+
except requests.exceptions.RequestException as e:
|
|
130
|
+
raise InterpreterError(f"API request failed: {e}") from e
|
|
131
|
+
except ValueError as e:
|
|
132
|
+
raise InterpreterError(f"Failed to decode JSON response: {e}") from e
|
|
133
|
+
|
|
134
|
+
|
|
135
|
+
def execute(
|
|
136
|
+
step: Invoke, stream_fn: Callable | None = None, **kwargs: dict[str, Any]
|
|
137
|
+
) -> list[Variable]:
|
|
138
|
+
"""Execute an Invoke step.
|
|
139
|
+
|
|
140
|
+
Args:
|
|
141
|
+
step: The Invoke step to execute.
|
|
142
|
+
**kwargs: Additional keyword arguments.
|
|
143
|
+
|
|
144
|
+
Returns:
|
|
145
|
+
List of output variables with their values set.
|
|
146
|
+
"""
|
|
147
|
+
logger.debug(f"Executing invoke step: {step.id}")
|
|
148
|
+
|
|
149
|
+
# Create lookup maps for efficient access
|
|
150
|
+
step_inputs_map = {var.id: var for var in step.inputs}
|
|
151
|
+
step_outputs_map = {var.id: var for var in step.outputs}
|
|
152
|
+
tool_inputs_map = step.tool.inputs or {}
|
|
153
|
+
tool_outputs_map = step.tool.outputs or {}
|
|
154
|
+
|
|
155
|
+
# Build inputs dictionary using input bindings
|
|
156
|
+
tool_inputs = {}
|
|
157
|
+
for tool_input_name, step_input_id in step.input_bindings.items():
|
|
158
|
+
# Validate tool parameter exists
|
|
159
|
+
if tool_input_name not in tool_inputs_map:
|
|
160
|
+
raise InterpreterError(
|
|
161
|
+
f"Tool input parameter '{tool_input_name}' not found in tool definition"
|
|
162
|
+
)
|
|
163
|
+
tool_param = tool_inputs_map[tool_input_name]
|
|
164
|
+
|
|
165
|
+
if step_input_id in step_inputs_map:
|
|
166
|
+
step_input = step_inputs_map[step_input_id]
|
|
167
|
+
# Check if input is set
|
|
168
|
+
if step_input.is_set():
|
|
169
|
+
tool_inputs[tool_input_name] = step_input.value
|
|
170
|
+
elif not tool_param.optional:
|
|
43
171
|
raise InterpreterError(
|
|
44
|
-
f"
|
|
172
|
+
f"Input '{step_input_id}' is required but not set"
|
|
45
173
|
)
|
|
46
|
-
|
|
47
|
-
|
|
174
|
+
else:
|
|
175
|
+
logging.warning(
|
|
176
|
+
f"Step input '{step_input_id}' not found in step inputs, using it as literal for {tool_input_name}"
|
|
177
|
+
)
|
|
178
|
+
tool_inputs[tool_input_name] = step_input_id
|
|
179
|
+
|
|
180
|
+
# Execute the tool
|
|
181
|
+
if isinstance(step.tool, PythonFunctionTool):
|
|
182
|
+
result = _execute_function_tool(step.tool, tool_inputs)
|
|
183
|
+
elif isinstance(step.tool, APITool):
|
|
184
|
+
result = _execute_api_tool(step.tool, tool_inputs)
|
|
48
185
|
else:
|
|
49
186
|
raise InterpreterError(
|
|
50
|
-
f"
|
|
187
|
+
f"Unsupported tool type: {type(step.tool).__name__}"
|
|
51
188
|
)
|
|
52
189
|
|
|
53
|
-
|
|
190
|
+
# Map results to output variables using output bindings
|
|
191
|
+
for tool_output_name, step_output_id in step.output_bindings.items():
|
|
192
|
+
# Validate step output exists
|
|
193
|
+
if step_output_id not in step_outputs_map:
|
|
194
|
+
raise InterpreterError(
|
|
195
|
+
f"Step output '{step_output_id}' not found in step outputs"
|
|
196
|
+
)
|
|
197
|
+
step_output = step_outputs_map[step_output_id]
|
|
198
|
+
|
|
199
|
+
# Validate tool output parameter exists
|
|
200
|
+
if tool_output_name not in tool_outputs_map:
|
|
201
|
+
raise InterpreterError(
|
|
202
|
+
f"Tool output parameter '{tool_output_name}' not found in tool definition"
|
|
203
|
+
)
|
|
204
|
+
tool_output_param = tool_outputs_map[tool_output_name]
|
|
205
|
+
|
|
206
|
+
# Extract the value from the result
|
|
207
|
+
if isinstance(result, dict):
|
|
208
|
+
if tool_output_name in result:
|
|
209
|
+
step_output.value = result[tool_output_name]
|
|
210
|
+
elif not tool_output_param.optional:
|
|
211
|
+
raise InterpreterError(
|
|
212
|
+
f"Tool output '{tool_output_name}' not found in result. "
|
|
213
|
+
f"Available keys: {list(result.keys())}"
|
|
214
|
+
)
|
|
215
|
+
else:
|
|
216
|
+
# Single output case - use the entire result
|
|
217
|
+
step_output.value = result
|
|
218
|
+
|
|
219
|
+
return step.outputs
|
|
@@ -1 +1 @@
|
|
|
1
|
-
<!DOCTYPE html><!--
|
|
1
|
+
<!DOCTYPE html><!--nUaw6_IwRwPqkzwe5s725--><html lang="en"><head><meta charSet="utf-8"/><meta name="viewport" content="width=device-width, initial-scale=1"/><link rel="preload" href="./_next/static/media/4cf2300e9c8272f7-s.p.woff2" as="font" crossorigin="" type="font/woff2"/><link rel="preload" href="./_next/static/media/93f479601ee12b01-s.p.woff2" as="font" crossorigin="" type="font/woff2"/><link rel="stylesheet" href="./_next/static/css/b40532b0db09cce3.css" data-precedence="next"/><link rel="preload" as="script" fetchPriority="low" href="./_next/static/chunks/webpack-08642e441b39b6c2.js"/><script src="./_next/static/chunks/4bd1b696-cf72ae8a39fa05aa.js" async=""></script><script src="./_next/static/chunks/964-2b041321a01cbf56.js" async=""></script><script src="./_next/static/chunks/main-app-6fc6346bc8f7f163.js" async=""></script><meta name="robots" content="noindex"/><meta name="next-size-adjust" content=""/><title>404: This page could not be found.</title><title>Create Next App</title><meta name="description" content="Generated by create next app"/><link rel="icon" href="/ui/favicon.ico" type="image/x-icon" sizes="16x16"/><script src="./_next/static/chunks/polyfills-42372ed130431b0a.js" noModule=""></script></head><body class="__variable_c57559 __variable_152ec0 antialiased"><div hidden=""><!--$--><!--/$--></div><div style="font-family:system-ui,"Segoe UI",Roboto,Helvetica,Arial,sans-serif,"Apple Color Emoji","Segoe UI Emoji";height:100vh;text-align:center;display:flex;flex-direction:column;align-items:center;justify-content:center"><div><style>body{color:#000;background:#fff;margin:0}.next-error-h1{border-right:1px solid rgba(0,0,0,.3)}@media (prefers-color-scheme:dark){body{color:#fff;background:#000}.next-error-h1{border-right:1px solid rgba(255,255,255,.3)}}</style><h1 class="next-error-h1" style="display:inline-block;margin:0 20px 0 0;padding:0 23px 0 0;font-size:24px;font-weight:500;vertical-align:top;line-height:49px">404</h1><div style="display:inline-block"><h2 style="font-size:14px;font-weight:400;line-height:49px;margin:0">This page could not be found.</h2></div></div></div><!--$--><!--/$--><script src="./_next/static/chunks/webpack-08642e441b39b6c2.js" id="_R_" async=""></script><script>(self.__next_f=self.__next_f||[]).push([0])</script><script>self.__next_f.push([1,"1:\"$Sreact.fragment\"\n2:I[7555,[],\"\"]\n3:I[1295,[],\"\"]\n4:I[9665,[],\"OutletBoundary\"]\n6:I[4911,[],\"AsyncMetadataOutlet\"]\n8:I[9665,[],\"ViewportBoundary\"]\na:I[9665,[],\"MetadataBoundary\"]\nb:\"$Sreact.suspense\"\nd:I[8393,[],\"\"]\n:HL[\"./_next/static/media/4cf2300e9c8272f7-s.p.woff2\",\"font\",{\"crossOrigin\":\"\",\"type\":\"font/woff2\"}]\n:HL[\"./_next/static/media/93f479601ee12b01-s.p.woff2\",\"font\",{\"crossOrigin\":\"\",\"type\":\"font/woff2\"}]\n:HL[\"./_next/static/css/b40532b0db09cce3.css\",\"style\"]\n"])</script><script>self.__next_f.push([1,"0:{\"P\":null,\"b\":\"nUaw6_IwRwPqkzwe5s725\",\"p\":\".\",\"c\":[\"\",\"_not-found\",\"\"],\"i\":false,\"f\":[[[\"\",{\"children\":[\"/_not-found\",{\"children\":[\"__PAGE__\",{}]}]},\"$undefined\",\"$undefined\",true],[\"\",[\"$\",\"$1\",\"c\",{\"children\":[[[\"$\",\"link\",\"0\",{\"rel\":\"stylesheet\",\"href\":\"./_next/static/css/b40532b0db09cce3.css\",\"precedence\":\"next\",\"crossOrigin\":\"$undefined\",\"nonce\":\"$undefined\"}]],[\"$\",\"html\",null,{\"lang\":\"en\",\"children\":[\"$\",\"body\",null,{\"className\":\"__variable_c57559 __variable_152ec0 antialiased\",\"children\":[\"$\",\"$L2\",null,{\"parallelRouterKey\":\"children\",\"error\":\"$undefined\",\"errorStyles\":\"$undefined\",\"errorScripts\":\"$undefined\",\"template\":[\"$\",\"$L3\",null,{}],\"templateStyles\":\"$undefined\",\"templateScripts\":\"$undefined\",\"notFound\":\"$undefined\",\"forbidden\":\"$undefined\",\"unauthorized\":\"$undefined\"}]}]}]]}],{\"children\":[\"/_not-found\",[\"$\",\"$1\",\"c\",{\"children\":[null,[\"$\",\"$L2\",null,{\"parallelRouterKey\":\"children\",\"error\":\"$undefined\",\"errorStyles\":\"$undefined\",\"errorScripts\":\"$undefined\",\"template\":[\"$\",\"$L3\",null,{}],\"templateStyles\":\"$undefined\",\"templateScripts\":\"$undefined\",\"notFound\":\"$undefined\",\"forbidden\":\"$undefined\",\"unauthorized\":\"$undefined\"}]]}],{\"children\":[\"__PAGE__\",[\"$\",\"$1\",\"c\",{\"children\":[[[\"$\",\"title\",null,{\"children\":\"404: This page could not be found.\"}],[\"$\",\"div\",null,{\"style\":{\"fontFamily\":\"system-ui,\\\"Segoe UI\\\",Roboto,Helvetica,Arial,sans-serif,\\\"Apple Color Emoji\\\",\\\"Segoe UI Emoji\\\"\",\"height\":\"100vh\",\"textAlign\":\"center\",\"display\":\"flex\",\"flexDirection\":\"column\",\"alignItems\":\"center\",\"justifyContent\":\"center\"},\"children\":[\"$\",\"div\",null,{\"children\":[[\"$\",\"style\",null,{\"dangerouslySetInnerHTML\":{\"__html\":\"body{color:#000;background:#fff;margin:0}.next-error-h1{border-right:1px solid rgba(0,0,0,.3)}@media (prefers-color-scheme:dark){body{color:#fff;background:#000}.next-error-h1{border-right:1px solid rgba(255,255,255,.3)}}\"}}],[\"$\",\"h1\",null,{\"className\":\"next-error-h1\",\"style\":{\"display\":\"inline-block\",\"margin\":\"0 20px 0 0\",\"padding\":\"0 23px 0 0\",\"fontSize\":24,\"fontWeight\":500,\"verticalAlign\":\"top\",\"lineHeight\":\"49px\"},\"children\":404}],[\"$\",\"div\",null,{\"style\":{\"display\":\"inline-block\"},\"children\":[\"$\",\"h2\",null,{\"style\":{\"fontSize\":14,\"fontWeight\":400,\"lineHeight\":\"49px\",\"margin\":0},\"children\":\"This page could not be found.\"}]}]]}]}]],null,[\"$\",\"$L4\",null,{\"children\":[\"$L5\",[\"$\",\"$L6\",null,{\"promise\":\"$@7\"}]]}]]}],{},null,false]},null,false]},null,false],[\"$\",\"$1\",\"h\",{\"children\":[[\"$\",\"meta\",null,{\"name\":\"robots\",\"content\":\"noindex\"}],[[\"$\",\"$L8\",null,{\"children\":\"$L9\"}],[\"$\",\"meta\",null,{\"name\":\"next-size-adjust\",\"content\":\"\"}]],[\"$\",\"$La\",null,{\"children\":[\"$\",\"div\",null,{\"hidden\":true,\"children\":[\"$\",\"$b\",null,{\"fallback\":null,\"children\":\"$Lc\"}]}]}]]}],false]],\"m\":\"$undefined\",\"G\":[\"$d\",[]],\"s\":false,\"S\":true}\n"])</script><script>self.__next_f.push([1,"9:[[\"$\",\"meta\",\"0\",{\"charSet\":\"utf-8\"}],[\"$\",\"meta\",\"1\",{\"name\":\"viewport\",\"content\":\"width=device-width, initial-scale=1\"}]]\n5:null\n"])</script><script>self.__next_f.push([1,"e:I[8175,[],\"IconMark\"]\n7:{\"metadata\":[[\"$\",\"title\",\"0\",{\"children\":\"Create Next App\"}],[\"$\",\"meta\",\"1\",{\"name\":\"description\",\"content\":\"Generated by create next app\"}],[\"$\",\"link\",\"2\",{\"rel\":\"icon\",\"href\":\"/ui/favicon.ico\",\"type\":\"image/x-icon\",\"sizes\":\"16x16\"}],[\"$\",\"$Le\",\"3\",{}]],\"error\":null,\"digest\":\"$undefined\"}\n"])</script><script>self.__next_f.push([1,"c:\"$7:metadata\"\n"])</script></body></html>
|
qtype/interpreter/ui/404.html
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
<!DOCTYPE html><!--
|
|
1
|
+
<!DOCTYPE html><!--nUaw6_IwRwPqkzwe5s725--><html lang="en"><head><meta charSet="utf-8"/><meta name="viewport" content="width=device-width, initial-scale=1"/><link rel="preload" href="./_next/static/media/4cf2300e9c8272f7-s.p.woff2" as="font" crossorigin="" type="font/woff2"/><link rel="preload" href="./_next/static/media/93f479601ee12b01-s.p.woff2" as="font" crossorigin="" type="font/woff2"/><link rel="stylesheet" href="./_next/static/css/b40532b0db09cce3.css" data-precedence="next"/><link rel="preload" as="script" fetchPriority="low" href="./_next/static/chunks/webpack-08642e441b39b6c2.js"/><script src="./_next/static/chunks/4bd1b696-cf72ae8a39fa05aa.js" async=""></script><script src="./_next/static/chunks/964-2b041321a01cbf56.js" async=""></script><script src="./_next/static/chunks/main-app-6fc6346bc8f7f163.js" async=""></script><meta name="robots" content="noindex"/><meta name="next-size-adjust" content=""/><title>404: This page could not be found.</title><title>Create Next App</title><meta name="description" content="Generated by create next app"/><link rel="icon" href="/ui/favicon.ico" type="image/x-icon" sizes="16x16"/><script src="./_next/static/chunks/polyfills-42372ed130431b0a.js" noModule=""></script></head><body class="__variable_c57559 __variable_152ec0 antialiased"><div hidden=""><!--$--><!--/$--></div><div style="font-family:system-ui,"Segoe UI",Roboto,Helvetica,Arial,sans-serif,"Apple Color Emoji","Segoe UI Emoji";height:100vh;text-align:center;display:flex;flex-direction:column;align-items:center;justify-content:center"><div><style>body{color:#000;background:#fff;margin:0}.next-error-h1{border-right:1px solid rgba(0,0,0,.3)}@media (prefers-color-scheme:dark){body{color:#fff;background:#000}.next-error-h1{border-right:1px solid rgba(255,255,255,.3)}}</style><h1 class="next-error-h1" style="display:inline-block;margin:0 20px 0 0;padding:0 23px 0 0;font-size:24px;font-weight:500;vertical-align:top;line-height:49px">404</h1><div style="display:inline-block"><h2 style="font-size:14px;font-weight:400;line-height:49px;margin:0">This page could not be found.</h2></div></div></div><!--$--><!--/$--><script src="./_next/static/chunks/webpack-08642e441b39b6c2.js" id="_R_" async=""></script><script>(self.__next_f=self.__next_f||[]).push([0])</script><script>self.__next_f.push([1,"1:\"$Sreact.fragment\"\n2:I[7555,[],\"\"]\n3:I[1295,[],\"\"]\n4:I[9665,[],\"OutletBoundary\"]\n6:I[4911,[],\"AsyncMetadataOutlet\"]\n8:I[9665,[],\"ViewportBoundary\"]\na:I[9665,[],\"MetadataBoundary\"]\nb:\"$Sreact.suspense\"\nd:I[8393,[],\"\"]\n:HL[\"./_next/static/media/4cf2300e9c8272f7-s.p.woff2\",\"font\",{\"crossOrigin\":\"\",\"type\":\"font/woff2\"}]\n:HL[\"./_next/static/media/93f479601ee12b01-s.p.woff2\",\"font\",{\"crossOrigin\":\"\",\"type\":\"font/woff2\"}]\n:HL[\"./_next/static/css/b40532b0db09cce3.css\",\"style\"]\n"])</script><script>self.__next_f.push([1,"0:{\"P\":null,\"b\":\"nUaw6_IwRwPqkzwe5s725\",\"p\":\".\",\"c\":[\"\",\"_not-found\",\"\"],\"i\":false,\"f\":[[[\"\",{\"children\":[\"/_not-found\",{\"children\":[\"__PAGE__\",{}]}]},\"$undefined\",\"$undefined\",true],[\"\",[\"$\",\"$1\",\"c\",{\"children\":[[[\"$\",\"link\",\"0\",{\"rel\":\"stylesheet\",\"href\":\"./_next/static/css/b40532b0db09cce3.css\",\"precedence\":\"next\",\"crossOrigin\":\"$undefined\",\"nonce\":\"$undefined\"}]],[\"$\",\"html\",null,{\"lang\":\"en\",\"children\":[\"$\",\"body\",null,{\"className\":\"__variable_c57559 __variable_152ec0 antialiased\",\"children\":[\"$\",\"$L2\",null,{\"parallelRouterKey\":\"children\",\"error\":\"$undefined\",\"errorStyles\":\"$undefined\",\"errorScripts\":\"$undefined\",\"template\":[\"$\",\"$L3\",null,{}],\"templateStyles\":\"$undefined\",\"templateScripts\":\"$undefined\",\"notFound\":\"$undefined\",\"forbidden\":\"$undefined\",\"unauthorized\":\"$undefined\"}]}]}]]}],{\"children\":[\"/_not-found\",[\"$\",\"$1\",\"c\",{\"children\":[null,[\"$\",\"$L2\",null,{\"parallelRouterKey\":\"children\",\"error\":\"$undefined\",\"errorStyles\":\"$undefined\",\"errorScripts\":\"$undefined\",\"template\":[\"$\",\"$L3\",null,{}],\"templateStyles\":\"$undefined\",\"templateScripts\":\"$undefined\",\"notFound\":\"$undefined\",\"forbidden\":\"$undefined\",\"unauthorized\":\"$undefined\"}]]}],{\"children\":[\"__PAGE__\",[\"$\",\"$1\",\"c\",{\"children\":[[[\"$\",\"title\",null,{\"children\":\"404: This page could not be found.\"}],[\"$\",\"div\",null,{\"style\":{\"fontFamily\":\"system-ui,\\\"Segoe UI\\\",Roboto,Helvetica,Arial,sans-serif,\\\"Apple Color Emoji\\\",\\\"Segoe UI Emoji\\\"\",\"height\":\"100vh\",\"textAlign\":\"center\",\"display\":\"flex\",\"flexDirection\":\"column\",\"alignItems\":\"center\",\"justifyContent\":\"center\"},\"children\":[\"$\",\"div\",null,{\"children\":[[\"$\",\"style\",null,{\"dangerouslySetInnerHTML\":{\"__html\":\"body{color:#000;background:#fff;margin:0}.next-error-h1{border-right:1px solid rgba(0,0,0,.3)}@media (prefers-color-scheme:dark){body{color:#fff;background:#000}.next-error-h1{border-right:1px solid rgba(255,255,255,.3)}}\"}}],[\"$\",\"h1\",null,{\"className\":\"next-error-h1\",\"style\":{\"display\":\"inline-block\",\"margin\":\"0 20px 0 0\",\"padding\":\"0 23px 0 0\",\"fontSize\":24,\"fontWeight\":500,\"verticalAlign\":\"top\",\"lineHeight\":\"49px\"},\"children\":404}],[\"$\",\"div\",null,{\"style\":{\"display\":\"inline-block\"},\"children\":[\"$\",\"h2\",null,{\"style\":{\"fontSize\":14,\"fontWeight\":400,\"lineHeight\":\"49px\",\"margin\":0},\"children\":\"This page could not be found.\"}]}]]}]}]],null,[\"$\",\"$L4\",null,{\"children\":[\"$L5\",[\"$\",\"$L6\",null,{\"promise\":\"$@7\"}]]}]]}],{},null,false]},null,false]},null,false],[\"$\",\"$1\",\"h\",{\"children\":[[\"$\",\"meta\",null,{\"name\":\"robots\",\"content\":\"noindex\"}],[[\"$\",\"$L8\",null,{\"children\":\"$L9\"}],[\"$\",\"meta\",null,{\"name\":\"next-size-adjust\",\"content\":\"\"}]],[\"$\",\"$La\",null,{\"children\":[\"$\",\"div\",null,{\"hidden\":true,\"children\":[\"$\",\"$b\",null,{\"fallback\":null,\"children\":\"$Lc\"}]}]}]]}],false]],\"m\":\"$undefined\",\"G\":[\"$d\",[]],\"s\":false,\"S\":true}\n"])</script><script>self.__next_f.push([1,"9:[[\"$\",\"meta\",\"0\",{\"charSet\":\"utf-8\"}],[\"$\",\"meta\",\"1\",{\"name\":\"viewport\",\"content\":\"width=device-width, initial-scale=1\"}]]\n5:null\n"])</script><script>self.__next_f.push([1,"e:I[8175,[],\"IconMark\"]\n7:{\"metadata\":[[\"$\",\"title\",\"0\",{\"children\":\"Create Next App\"}],[\"$\",\"meta\",\"1\",{\"name\":\"description\",\"content\":\"Generated by create next app\"}],[\"$\",\"link\",\"2\",{\"rel\":\"icon\",\"href\":\"/ui/favicon.ico\",\"type\":\"image/x-icon\",\"sizes\":\"16x16\"}],[\"$\",\"$Le\",\"3\",{}]],\"error\":null,\"digest\":\"$undefined\"}\n"])</script><script>self.__next_f.push([1,"c:\"$7:metadata\"\n"])</script></body></html>
|