qtype 0.1.12__py3-none-any.whl → 0.1.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.
Files changed (252) hide show
  1. qtype/` +0 -0
  2. qtype/application/__init__.py +0 -2
  3. qtype/application/converters/tools_from_api.py +28 -22
  4. qtype/application/converters/tools_from_module.py +66 -32
  5. qtype/commands/generate.py +90 -7
  6. qtype/commands/run.py +116 -44
  7. qtype/docs/.pages +8 -0
  8. {docs → qtype/docs}/Concepts/mental-model-and-philosophy.md +1 -1
  9. qtype/docs/Contributing/.pages +4 -0
  10. {docs → qtype/docs}/Contributing/index.md +8 -1
  11. {docs → qtype/docs}/Gallery/dataflow_pipelines.md +3 -2
  12. {docs → qtype/docs}/Gallery/research_assistant.md +3 -4
  13. {docs → qtype/docs}/Gallery/simple_chatbot.md +3 -1
  14. {docs → qtype/docs}/How To/Authentication/configure_aws_authentication.md +2 -2
  15. {docs → qtype/docs}/How To/Authentication/use_api_key_authentication.md +2 -2
  16. {docs → qtype/docs}/How To/Command Line Usage/load_multiple_inputs_from_files.md +24 -9
  17. {docs → qtype/docs}/How To/Command Line Usage/pass_inputs_on_the_cli.md +3 -3
  18. {docs → qtype/docs}/How To/Command Line Usage/serve_with_auto_reload.md +3 -2
  19. {docs → qtype/docs}/How To/Data Processing/adjust_concurrency.md +3 -4
  20. {docs → qtype/docs}/How To/Data Processing/cache_step_results.md +2 -2
  21. {docs → qtype/docs}/How To/Data Processing/decode_json_xml.md +1 -1
  22. {docs → qtype/docs}/How To/Data Processing/explode_collections.md +2 -2
  23. {docs → qtype/docs}/How To/Data Processing/gather_results.md +4 -4
  24. qtype/docs/How To/Data Processing/invoke_other_flows.md +71 -0
  25. qtype/docs/How To/Data Processing/load_data_from_athena.md +49 -0
  26. qtype/docs/How To/Data Processing/read_data_from_files.md +61 -0
  27. {docs → qtype/docs}/How To/Data Processing/read_sql_databases.md +2 -3
  28. {docs → qtype/docs}/How To/Data Processing/write_data_to_file.md +1 -2
  29. {docs → qtype/docs}/How To/Invoke Models/call_large_language_models.md +1 -1
  30. {docs → qtype/docs}/How To/Invoke Models/create_embeddings.md +1 -1
  31. {docs → qtype/docs}/How To/Invoke Models/reuse_prompts_with_templates.md +2 -3
  32. {docs → qtype/docs}/How To/Language Features/include_raw_text_from_other_files.md +2 -1
  33. {docs → qtype/docs}/How To/Language Features/reference_entities_by_id.md +2 -2
  34. qtype/docs/How To/Language Features/use_agent_skills.md +29 -0
  35. {docs → qtype/docs}/How To/Language Features/use_environment_variables.md +2 -1
  36. qtype/docs/How To/Language Features/use_optional_variables.md +42 -0
  37. {docs → qtype/docs}/How To/Language Features/use_qtype_mcp.md +4 -4
  38. {docs → qtype/docs}/How To/Observability & Debugging/trace_calls_with_open_telemetry.md +1 -1
  39. {docs → qtype/docs}/How To/Observability & Debugging/validate_qtype_yaml.md +3 -2
  40. {docs → qtype/docs}/How To/Observability & Debugging/visualize_application_architecture.md +1 -1
  41. {docs → qtype/docs}/How To/Qtype Server/serve_flows_as_apis.md +3 -3
  42. {docs → qtype/docs}/How To/Qtype Server/serve_flows_as_ui.md +2 -3
  43. {docs → qtype/docs}/How To/Qtype Server/use_conversational_interfaces.md +1 -4
  44. {docs → qtype/docs}/How To/Qtype Server/use_variables_with_ui_hints.md +3 -2
  45. {docs → qtype/docs}/How To/Tools & Integration/bind_tool_inputs_and_outputs.md +1 -2
  46. {docs → qtype/docs}/How To/Tools & Integration/create_tools_from_openapi_specifications.md +10 -14
  47. {docs → qtype/docs}/How To/Tools & Integration/create_tools_from_python_modules.md +5 -8
  48. {docs → qtype/docs}/Reference/cli.md +13 -15
  49. {docs → qtype/docs}/Reference/plugins.md +4 -0
  50. {docs → qtype/docs}/Reference/semantic-validation-rules.md +6 -1
  51. qtype/docs/Tutorials/.pages +1 -0
  52. {docs → qtype/docs}/Tutorials/01-first-qtype-application.md +3 -2
  53. {docs → qtype/docs}/Tutorials/02-conversational-chatbot.md +3 -3
  54. {docs → qtype/docs}/Tutorials/03-structured-data.md +9 -10
  55. {docs → qtype/docs}/Tutorials/04-tools-and-function-calling.md +12 -19
  56. {docs → qtype/docs}/components/APITool.md +1 -1
  57. qtype/docs/components/Aggregate.md +7 -0
  58. qtype/docs/components/Collect.md +6 -0
  59. qtype/docs/components/Construct.md +6 -0
  60. {docs → qtype/docs}/components/DocumentEmbedder.md +0 -1
  61. {docs → qtype/docs}/components/DocumentSplitter.md +0 -1
  62. qtype/docs/components/Explode.md +5 -0
  63. {docs → qtype/docs}/components/FieldExtractor.md +2 -1
  64. qtype/docs/components/InvokeFlow.md +8 -0
  65. qtype/docs/components/InvokeTool.md +8 -0
  66. {docs → qtype/docs}/components/PrimitiveTypeEnum.md +0 -1
  67. {docs → qtype/docs}/components/Source.md +0 -1
  68. {docs → qtype/docs}/components/Step.md +0 -1
  69. {docs → qtype/docs}/components/Tool.md +2 -2
  70. {docs → qtype/docs}/components/Variable.md +2 -0
  71. qtype/docs/legacy_how_tos/.pages +6 -0
  72. qtype/docs/skills/architect/SKILL.md +188 -0
  73. qtype/docs/skills/architect/references/cheatsheet.md +198 -0
  74. qtype/docs/skills/architect/references/patterns.md +29 -0
  75. qtype/docs/stylesheets/extra.css +27 -0
  76. qtype/dsl/linker.py +8 -0
  77. qtype/dsl/model.py +177 -84
  78. qtype/examples/data_processing/athena_query.qtype.yaml +56 -0
  79. qtype/examples/data_processing/batch_inputs.csv +5 -0
  80. qtype/examples/data_processing/create_sample_db.py +129 -0
  81. qtype/examples/data_processing/invoke_other_flows.qtype.yaml +98 -0
  82. qtype/examples/data_processing/reviews.db +0 -0
  83. qtype/examples/data_processing/sample_article.txt +1 -0
  84. qtype/examples/data_processing/sample_documents.jsonl +5 -0
  85. qtype/examples/language_features/optional_variables.qtype.yaml +32 -0
  86. qtype/examples/language_features/story_prompt.txt +6 -0
  87. qtype/examples/legacy/data/customers.csv +6 -0
  88. qtype/examples/legacy/echo/readme.md +29 -0
  89. qtype/examples/legacy/qtype_plugin_example.py +51 -0
  90. qtype/examples/legacy/sample_data.txt +43 -0
  91. qtype/examples/legacy/vertex/README.md +11 -0
  92. qtype/examples/research_assistant/tavily.qtype.yaml +216 -0
  93. {examples → qtype/examples}/tutorials/03_structured_data.qtype.yaml +2 -2
  94. {examples → qtype/examples}/tutorials/04_tools_and_function_calling.qtype.yaml +5 -5
  95. qtype/interpreter/base/stream_emitter.py +19 -13
  96. qtype/interpreter/converters.py +142 -26
  97. qtype/interpreter/executors/agent_executor.py +2 -3
  98. qtype/interpreter/executors/aggregate_executor.py +3 -4
  99. qtype/interpreter/executors/construct_executor.py +15 -15
  100. qtype/interpreter/executors/doc_to_text_executor.py +1 -3
  101. qtype/interpreter/executors/field_extractor_executor.py +13 -12
  102. qtype/interpreter/executors/file_source_executor.py +18 -31
  103. qtype/interpreter/executors/invoke_embedding_executor.py +1 -4
  104. qtype/interpreter/executors/invoke_flow_executor.py +2 -2
  105. qtype/interpreter/executors/invoke_tool_executor.py +19 -18
  106. qtype/interpreter/executors/llm_inference_executor.py +16 -18
  107. qtype/interpreter/executors/prompt_template_executor.py +1 -3
  108. qtype/interpreter/tools/function_tool_helper.py +11 -10
  109. qtype/interpreter/types.py +89 -4
  110. qtype/interpreter/typing.py +31 -32
  111. qtype/mcp/server.py +312 -57
  112. {schema → qtype/schema}/qtype.schema.json +77 -79
  113. qtype/semantic/checker.py +19 -0
  114. qtype/semantic/generate.py +3 -6
  115. qtype/semantic/model.py +26 -33
  116. qtype/semantic/resolver.py +7 -0
  117. qtype/semantic/visualize.py +8 -3
  118. {qtype-0.1.12.dist-info → qtype-0.1.13.dist-info}/METADATA +47 -46
  119. qtype-0.1.13.dist-info/RECORD +352 -0
  120. {qtype-0.1.12.dist-info → qtype-0.1.13.dist-info}/WHEEL +1 -2
  121. docs/How To/Data Processing/read_data_from_files.md +0 -35
  122. docs/components/Aggregate.md +0 -8
  123. docs/components/InvokeFlow.md +0 -8
  124. docs/components/InvokeTool.md +0 -8
  125. docs/components/ToolParameter.md +0 -6
  126. examples/research_assistant/tavily.qtype.yaml +0 -289
  127. qtype/application/facade.py +0 -177
  128. qtype-0.1.12.dist-info/RECORD +0 -325
  129. qtype-0.1.12.dist-info/top_level.txt +0 -1
  130. {docs → qtype/docs}/Contributing/roadmap.md +0 -0
  131. {docs → qtype/docs}/Decisions/ADR-001-Chat-vs-Completion-Endpoint-Features.md +0 -0
  132. {docs → qtype/docs}/Gallery/dataflow_pipelines.mermaid +0 -0
  133. {docs → qtype/docs}/Gallery/research_assistant.mermaid +0 -0
  134. {docs → qtype/docs}/Gallery/simple_chatbot.mermaid +0 -0
  135. {docs → qtype/docs}/How To/Language Features/include_qtype_yaml.md +0 -0
  136. {docs → qtype/docs}/How To/Observability & Debugging/visualize_example.mermaid +0 -0
  137. {docs → qtype/docs}/How To/Qtype Server/flow_as_ui.png +0 -0
  138. {docs → qtype/docs}/Tutorials/example_chat.png +0 -0
  139. {docs → qtype/docs}/Tutorials/index.md +0 -0
  140. {docs → qtype/docs}/components/APIKeyAuthProvider.md +0 -0
  141. {docs → qtype/docs}/components/AWSAuthProvider.md +0 -0
  142. {docs → qtype/docs}/components/AWSSecretManager.md +0 -0
  143. {docs → qtype/docs}/components/Agent.md +0 -0
  144. {docs → qtype/docs}/components/AggregateStats.md +0 -0
  145. {docs → qtype/docs}/components/Application.md +0 -0
  146. {docs → qtype/docs}/components/AuthorizationProvider.md +0 -0
  147. {docs → qtype/docs}/components/AuthorizationProviderList.md +0 -0
  148. {docs → qtype/docs}/components/BearerTokenAuthProvider.md +0 -0
  149. {docs → qtype/docs}/components/BedrockReranker.md +0 -0
  150. {docs → qtype/docs}/components/ChatContent.md +0 -0
  151. {docs → qtype/docs}/components/ChatMessage.md +0 -0
  152. {docs → qtype/docs}/components/ConstantPath.md +0 -0
  153. {docs → qtype/docs}/components/CustomType.md +0 -0
  154. {docs → qtype/docs}/components/Decoder.md +0 -0
  155. {docs → qtype/docs}/components/DecoderFormat.md +0 -0
  156. {docs → qtype/docs}/components/DocToTextConverter.md +0 -0
  157. {docs → qtype/docs}/components/Document.md +0 -0
  158. {docs → qtype/docs}/components/DocumentIndex.md +0 -0
  159. {docs → qtype/docs}/components/DocumentSearch.md +0 -0
  160. {docs → qtype/docs}/components/DocumentSource.md +0 -0
  161. {docs → qtype/docs}/components/Echo.md +0 -0
  162. {docs → qtype/docs}/components/Embedding.md +0 -0
  163. {docs → qtype/docs}/components/EmbeddingModel.md +0 -0
  164. {docs → qtype/docs}/components/FileSource.md +0 -0
  165. {docs → qtype/docs}/components/FileWriter.md +0 -0
  166. {docs → qtype/docs}/components/Flow.md +0 -0
  167. {docs → qtype/docs}/components/FlowInterface.md +0 -0
  168. {docs → qtype/docs}/components/Index.md +0 -0
  169. {docs → qtype/docs}/components/IndexUpsert.md +0 -0
  170. {docs → qtype/docs}/components/InvokeEmbedding.md +0 -0
  171. {docs → qtype/docs}/components/LLMInference.md +0 -0
  172. {docs → qtype/docs}/components/ListType.md +0 -0
  173. {docs → qtype/docs}/components/Memory.md +0 -0
  174. {docs → qtype/docs}/components/MessageRole.md +0 -0
  175. {docs → qtype/docs}/components/Model.md +0 -0
  176. {docs → qtype/docs}/components/ModelList.md +0 -0
  177. {docs → qtype/docs}/components/OAuth2AuthProvider.md +0 -0
  178. {docs → qtype/docs}/components/PromptTemplate.md +0 -0
  179. {docs → qtype/docs}/components/PythonFunctionTool.md +0 -0
  180. {docs → qtype/docs}/components/RAGChunk.md +0 -0
  181. {docs → qtype/docs}/components/RAGDocument.md +0 -0
  182. {docs → qtype/docs}/components/RAGSearchResult.md +0 -0
  183. {docs → qtype/docs}/components/Reranker.md +0 -0
  184. {docs → qtype/docs}/components/SQLSource.md +0 -0
  185. {docs → qtype/docs}/components/Search.md +0 -0
  186. {docs → qtype/docs}/components/SearchResult.md +0 -0
  187. {docs → qtype/docs}/components/SecretManager.md +0 -0
  188. {docs → qtype/docs}/components/SecretReference.md +0 -0
  189. {docs → qtype/docs}/components/TelemetrySink.md +0 -0
  190. {docs → qtype/docs}/components/ToolList.md +0 -0
  191. {docs → qtype/docs}/components/TypeList.md +0 -0
  192. {docs → qtype/docs}/components/VariableList.md +0 -0
  193. {docs → qtype/docs}/components/VectorIndex.md +0 -0
  194. {docs → qtype/docs}/components/VectorSearch.md +0 -0
  195. {docs → qtype/docs}/components/VertexAuthProvider.md +0 -0
  196. {docs → qtype/docs}/components/Writer.md +0 -0
  197. {docs → qtype/docs}/example_ui.png +0 -0
  198. {docs → qtype/docs}/index.md +0 -0
  199. {docs → qtype/docs}/legacy_how_tos/Configuration/modular-yaml.md +0 -0
  200. {docs → qtype/docs}/legacy_how_tos/Configuration/phoenix_projects.png +0 -0
  201. {docs → qtype/docs}/legacy_how_tos/Configuration/phoenix_traces.png +0 -0
  202. {docs → qtype/docs}/legacy_how_tos/Configuration/reference-by-id.md +0 -0
  203. {docs → qtype/docs}/legacy_how_tos/Configuration/telemetry-setup.md +0 -0
  204. {docs → qtype/docs}/legacy_how_tos/Data Types/custom-types.md +0 -0
  205. {docs → qtype/docs}/legacy_how_tos/Data Types/domain-types.md +0 -0
  206. {docs → qtype/docs}/legacy_how_tos/Debugging/visualize-apps.md +0 -0
  207. {docs → qtype/docs}/legacy_how_tos/Tools/api-tools.md +0 -0
  208. {docs → qtype/docs}/legacy_how_tos/Tools/python-tools.md +0 -0
  209. {examples → qtype/examples}/authentication/aws_authentication.qtype.yaml +0 -0
  210. {examples → qtype/examples}/conversational_ai/hello_world_chat.qtype.yaml +0 -0
  211. {examples → qtype/examples}/conversational_ai/simple_chatbot.qtype.yaml +0 -0
  212. {examples → qtype/examples}/data_processing/batch_processing.qtype.yaml +0 -0
  213. {examples → qtype/examples}/data_processing/cache_step_results.qtype.yaml +0 -0
  214. {examples → qtype/examples}/data_processing/collect_results.qtype.yaml +0 -0
  215. {examples → qtype/examples}/data_processing/dataflow_pipelines.qtype.yaml +0 -0
  216. {examples → qtype/examples}/data_processing/decode_json.qtype.yaml +0 -0
  217. {examples → qtype/examples}/data_processing/explode_items.qtype.yaml +0 -0
  218. {examples → qtype/examples}/data_processing/read_file.qtype.yaml +0 -0
  219. {examples → qtype/examples}/invoke_models/create_embeddings.qtype.yaml +0 -0
  220. {examples → qtype/examples}/invoke_models/simple_llm_call.qtype.yaml +0 -0
  221. {examples → qtype/examples}/language_features/include_raw.qtype.yaml +0 -0
  222. {examples → qtype/examples}/language_features/ui_hints.qtype.yaml +0 -0
  223. {examples → qtype/examples}/legacy/bedrock/data_analysis_with_telemetry.qtype.yaml +0 -0
  224. {examples → qtype/examples}/legacy/bedrock/hello_world.qtype.yaml +0 -0
  225. {examples → qtype/examples}/legacy/bedrock/hello_world_chat.qtype.yaml +0 -0
  226. {examples → qtype/examples}/legacy/bedrock/hello_world_chat_with_telemetry.qtype.yaml +0 -0
  227. {examples → qtype/examples}/legacy/bedrock/hello_world_chat_with_thinking.qtype.yaml +0 -0
  228. {examples → qtype/examples}/legacy/bedrock/hello_world_completion.qtype.yaml +0 -0
  229. {examples → qtype/examples}/legacy/bedrock/hello_world_completion_with_auth.qtype.yaml +0 -0
  230. {examples → qtype/examples}/legacy/bedrock/simple_agent_chat.qtype.yaml +0 -0
  231. {examples → qtype/examples}/legacy/chat_with_langfuse.qtype.yaml +0 -0
  232. {examples → qtype/examples}/legacy/data_processor.qtype.yaml +0 -0
  233. {examples → qtype/examples}/legacy/echo/debug_example.qtype.yaml +0 -0
  234. {examples → qtype/examples}/legacy/echo/prompt.qtype.yaml +0 -0
  235. {examples → qtype/examples}/legacy/echo/test.qtype.yaml +0 -0
  236. {examples → qtype/examples}/legacy/echo/video.qtype.yaml +0 -0
  237. {examples → qtype/examples}/legacy/field_extractor_example.qtype.yaml +0 -0
  238. {examples → qtype/examples}/legacy/multi_flow_example.qtype.yaml +0 -0
  239. {examples → qtype/examples}/legacy/openai/hello_world_chat.qtype.yaml +0 -0
  240. {examples → qtype/examples}/legacy/openai/hello_world_chat_with_telemetry.qtype.yaml +0 -0
  241. {examples → qtype/examples}/legacy/rag.qtype.yaml +0 -0
  242. {examples → qtype/examples}/legacy/time_utilities.qtype.yaml +0 -0
  243. {examples → qtype/examples}/legacy/vertex/hello_world_chat.qtype.yaml +0 -0
  244. {examples → qtype/examples}/legacy/vertex/hello_world_completion.qtype.yaml +0 -0
  245. {examples → qtype/examples}/legacy/vertex/hello_world_completion_with_auth.qtype.yaml +0 -0
  246. {examples → qtype/examples}/observability_debugging/trace_with_opentelemetry.qtype.yaml +0 -0
  247. {examples → qtype/examples}/research_assistant/research_assistant.qtype.yaml +0 -0
  248. {examples → qtype/examples}/research_assistant/tavily.oas.yaml +0 -0
  249. {examples → qtype/examples}/tutorials/01_hello_world.qtype.yaml +0 -0
  250. {examples → qtype/examples}/tutorials/02_conversational_chat.qtype.yaml +0 -0
  251. {qtype-0.1.12.dist-info → qtype-0.1.13.dist-info}/entry_points.txt +0 -0
  252. {qtype-0.1.12.dist-info → qtype-0.1.13.dist-info}/licenses/LICENSE +0 -0
qtype/` ADDED
File without changes
@@ -3,10 +3,8 @@
3
3
  from __future__ import annotations
4
4
 
5
5
  from . import commons, converters
6
- from .facade import QTypeFacade
7
6
 
8
7
  __all__ = [
9
- "QTypeFacade",
10
8
  "converters",
11
9
  "commons",
12
10
  ]
@@ -26,7 +26,7 @@ from qtype.dsl.model import (
26
26
  BearerTokenAuthProvider,
27
27
  CustomType,
28
28
  OAuth2AuthProvider,
29
- ToolParameter,
29
+ Variable,
30
30
  VariableType,
31
31
  )
32
32
 
@@ -202,9 +202,9 @@ def create_tool_parameters_from_body(
202
202
  existing_custom_types: dict[str, CustomType],
203
203
  schema_name_map: dict[int, str],
204
204
  default_param_name: str,
205
- ) -> dict[str, ToolParameter]:
205
+ ) -> list[Variable]:
206
206
  """
207
- Convert an OpenAPI Response or RequestBody to a dictionary of ToolParameters.
207
+ Convert an OpenAPI Response or RequestBody to a list of Variables.
208
208
 
209
209
  If the body has only one content type with an Object schema, flatten its properties
210
210
  to individual parameters. Otherwise, create a single parameter with the body type.
@@ -216,18 +216,18 @@ def create_tool_parameters_from_body(
216
216
  default_param_name: Name to use for non-flattened parameter
217
217
 
218
218
  Returns:
219
- Dictionary of parameter name to ToolParameter objects
219
+ List of Variable objects
220
220
  """
221
221
  # Check if we have content to analyze
222
222
  if not hasattr(oas, "content") or not oas.content:
223
- return {}
223
+ return []
224
224
 
225
225
  content = oas.content[0]
226
226
  input_type = to_variable_type(
227
227
  content, existing_custom_types, schema_name_map
228
228
  )
229
229
 
230
- # Convert CustomType to string ID for ToolParameter
230
+ # Convert CustomType to string ID for Variable
231
231
  input_type_value = (
232
232
  input_type.id if isinstance(input_type, CustomType) else input_type
233
233
  )
@@ -240,7 +240,7 @@ def create_tool_parameters_from_body(
240
240
  custom_type = existing_custom_types[input_type.id]
241
241
 
242
242
  # Flatten the custom type properties to individual parameters
243
- flattened_parameters = {}
243
+ flattened_parameters = []
244
244
  for prop_name, prop_type_str in custom_type.properties.items():
245
245
  # Check if the property is optional (has '?' suffix)
246
246
  is_optional = prop_type_str.endswith("?")
@@ -248,8 +248,10 @@ def create_tool_parameters_from_body(
248
248
  prop_type_str.rstrip("?") if is_optional else prop_type_str
249
249
  )
250
250
 
251
- flattened_parameters[prop_name] = ToolParameter(
252
- type=clean_type, optional=is_optional
251
+ flattened_parameters.append(
252
+ Variable.model_construct(
253
+ id=prop_name, type=clean_type, optional=is_optional
254
+ )
253
255
  )
254
256
 
255
257
  # remove the type from existing_custom_types to avoid confusion
@@ -258,11 +260,11 @@ def create_tool_parameters_from_body(
258
260
  return flattened_parameters
259
261
 
260
262
  # If not flattening, create a single parameter (e.g., for simple types or arrays)
261
- return {
262
- default_param_name: ToolParameter(
263
- type=input_type_value, optional=False
263
+ return [
264
+ Variable.model_construct(
265
+ id=default_param_name, type=input_type_value, optional=False
264
266
  )
265
- }
267
+ ]
266
268
 
267
269
 
268
270
  def to_api_tool(
@@ -297,7 +299,7 @@ def to_api_tool(
297
299
  ).replace("\n", " ")
298
300
 
299
301
  # Process inputs from request body and parameters
300
- inputs = {}
302
+ inputs = []
301
303
  if operation.request_body and operation.request_body.content:
302
304
  # Create input parameters from request body using the new function
303
305
  input_params = create_tool_parameters_from_body(
@@ -306,27 +308,31 @@ def to_api_tool(
306
308
  schema_name_map,
307
309
  default_param_name="request",
308
310
  )
309
- inputs.update(input_params)
311
+ inputs.extend(input_params)
310
312
 
311
313
  # Add path and query parameters as inputs
312
- parameters = {}
314
+ parameters = []
313
315
  for param in operation.parameters:
314
316
  if param.schema:
315
317
  param_type = _schema_to_qtype_type(
316
318
  param.schema, existing_custom_types, schema_name_map
317
319
  )
318
- # Convert to appropriate type for ToolParameter
320
+ # Convert to appropriate type for Variable
319
321
  param_type_value = (
320
322
  param_type.id
321
323
  if isinstance(param_type, CustomType)
322
324
  else param_type
323
325
  )
324
- parameters[param.name] = ToolParameter(
325
- type=param_type_value, optional=not param.required
326
+ parameters.append(
327
+ Variable.model_construct(
328
+ id=param.name,
329
+ type=param_type_value,
330
+ optional=not param.required,
331
+ )
326
332
  )
327
333
 
328
334
  # Process outputs from responses
329
- outputs = {}
335
+ outputs = []
330
336
  # Find the success response (200-299 status codes) or default response
331
337
  success_response = next(
332
338
  (r for r in operation.responses if r.code and 200 <= r.code < 300),
@@ -339,9 +345,9 @@ def to_api_tool(
339
345
  success_response,
340
346
  existing_custom_types,
341
347
  schema_name_map,
342
- default_param_name="response",
348
+ default_param_name=f"{tool_id}_response",
343
349
  )
344
- outputs.update(output_params)
350
+ outputs.extend(output_params)
345
351
 
346
352
  return APITool(
347
353
  id=tool_id,
@@ -10,7 +10,7 @@ from qtype.dsl.model import (
10
10
  CustomType,
11
11
  ListType,
12
12
  PythonFunctionTool,
13
- ToolParameter,
13
+ Variable,
14
14
  VariableType,
15
15
  )
16
16
 
@@ -43,14 +43,19 @@ def tools_from_module(
43
43
  f"No public functions found in module '{module_path}'"
44
44
  )
45
45
 
46
- custom_types: dict[str, CustomType] = {}
46
+ # Registry of actual Pydantic classes for validation
47
+ custom_type_registry: dict[str, Type[BaseModel]] = {}
48
+ # CustomType instances for YAML output
49
+ custom_type_models: dict[str, CustomType] = {}
47
50
 
48
51
  # Create Tool instances from functions
49
52
  tools = [
50
- _create_tool_from_function(func_name, func_info, custom_types)
53
+ _create_tool_from_function(
54
+ func_name, func_info, custom_type_registry, custom_type_models
55
+ )
51
56
  for func_name, func_info in functions.items()
52
57
  ]
53
- return (tools, list(custom_types.values()))
58
+ return (tools, list(custom_type_models.values()))
54
59
  except ImportError as e:
55
60
  raise ImportError(f"Cannot import module '{module_path}': {e}") from e
56
61
 
@@ -116,7 +121,8 @@ def _get_module_functions(
116
121
  def _create_tool_from_function(
117
122
  func_name: str,
118
123
  func_info: dict[str, Any],
119
- custom_types: dict[str, CustomType],
124
+ custom_type_registry: dict[str, Type[BaseModel]],
125
+ custom_type_models: dict[str, CustomType],
120
126
  ) -> PythonFunctionTool:
121
127
  """
122
128
  Convert function metadata into a Tool instance.
@@ -135,29 +141,38 @@ def _create_tool_from_function(
135
141
  else f"Function {func_name}"
136
142
  )
137
143
 
138
- # Create input parameters from function parameters
139
- inputs = {
140
- p["name"]: ToolParameter(
141
- type=_map_python_type_to_variable_type(p["type"], custom_types),
142
- optional=p["default"] != inspect.Parameter.empty,
144
+ # Create input parameters as list of Variables
145
+ inputs = [
146
+ Variable.model_validate(
147
+ {
148
+ "id": p["name"],
149
+ "type": _map_python_type_to_variable_type(
150
+ p["type"], custom_type_registry, custom_type_models
151
+ ),
152
+ "optional": p["default"] != inspect.Parameter.empty,
153
+ },
154
+ context={"custom_types": custom_type_registry},
143
155
  )
144
156
  for p in func_info["parameters"]
145
- }
146
-
147
- # # quick hack
148
- # for k, v in inputs.items():
149
- # if inspect.isclass(v.type) and issubclass(v.type, BaseModel):
150
- # v.type = str(v.type.__name__)
157
+ ]
151
158
 
152
159
  # Create output parameter based on return type
153
160
  tool_id = func_info["module"] + "." + func_name
154
161
 
155
162
  output_type = _map_python_type_to_variable_type(
156
- func_info["return_type"], custom_types
163
+ func_info["return_type"], custom_type_registry, custom_type_models
157
164
  )
158
165
 
159
- outputs = {"result": ToolParameter(type=output_type, optional=False)}
160
- # outputs['result'].type =
166
+ outputs = [
167
+ Variable.model_validate(
168
+ {
169
+ "id": f"{func_name}_result",
170
+ "type": output_type,
171
+ "optional": False,
172
+ },
173
+ context={"custom_types": custom_type_registry},
174
+ )
175
+ ]
161
176
 
162
177
  return PythonFunctionTool(
163
178
  id=tool_id,
@@ -172,7 +187,8 @@ def _create_tool_from_function(
172
187
 
173
188
  def _pydantic_to_custom_types(
174
189
  model_cls: Type[BaseModel],
175
- custom_types: dict[str, CustomType],
190
+ custom_type_registry: dict[str, Type[BaseModel]],
191
+ custom_type_models: dict[str, CustomType],
176
192
  ) -> str:
177
193
  """
178
194
  Converts a Pydantic BaseModel class into a QType CustomType.
@@ -184,15 +200,20 @@ def _pydantic_to_custom_types(
184
200
 
185
201
  Args:
186
202
  model_cls: The Pydantic model class to convert.
203
+ custom_type_registry: Registry of actual Pydantic classes for validation
204
+ custom_type_models: Dictionary of CustomType models for YAML output
187
205
 
188
206
  Returns:
189
- A dictionary mapping field names to their corresponding CustomType definitions.
207
+ The model name as a string type reference
190
208
  """
191
209
  properties = {}
192
210
  model_name = model_cls.__name__
193
- if model_name in custom_types:
211
+ if model_name in custom_type_registry:
194
212
  return model_name # Already processed
195
213
 
214
+ # Register the actual class for validation
215
+ custom_type_registry[model_name] = model_cls
216
+
196
217
  for field_name, field_info in model_cls.model_fields.items():
197
218
  # Use the annotation (the type hint) for the field
198
219
  field_type = field_info.annotation
@@ -202,22 +223,27 @@ def _pydantic_to_custom_types(
202
223
  )
203
224
  elif get_origin(field_type) is Union:
204
225
  # Assume the union means it's optional
226
+ # TODO: support proper unions
205
227
  field_type = [
206
228
  t for t in get_args(field_type) if t is not type(None)
207
229
  ][0]
208
- rv = _map_python_type_to_type_str(field_type, custom_types)
230
+ rv = _map_python_type_to_type_str(
231
+ field_type, custom_type_registry, custom_type_models
232
+ )
209
233
  properties[field_name] = f"{rv}?"
210
234
  elif get_origin(field_type) is list:
211
235
  inner_type = get_args(field_type)[0]
212
- rv = _map_python_type_to_type_str(inner_type, custom_types)
236
+ rv = _map_python_type_to_type_str(
237
+ inner_type, custom_type_registry, custom_type_models
238
+ )
213
239
  properties[field_name] = f"list[{rv}]"
214
240
  else:
215
241
  properties[field_name] = _map_python_type_to_type_str(
216
- field_type, custom_types
242
+ field_type, custom_type_registry, custom_type_models
217
243
  )
218
244
 
219
- # Add the custom type to the list
220
- custom_types[model_name] = CustomType(
245
+ # Add the CustomType model for YAML output
246
+ custom_type_models[model_name] = CustomType(
221
247
  id=model_name,
222
248
  properties=properties,
223
249
  description=model_cls.__doc__ or f"Custom type for {model_name}",
@@ -227,7 +253,8 @@ def _pydantic_to_custom_types(
227
253
 
228
254
  def _map_python_type_to_variable_type(
229
255
  python_type: Any,
230
- custom_types: dict[str, CustomType],
256
+ custom_type_registry: dict[str, Type[BaseModel]],
257
+ custom_type_models: dict[str, CustomType],
231
258
  ) -> str | VariableType:
232
259
  """
233
260
  Map Python type annotations to QType VariableType.
@@ -248,7 +275,9 @@ def _map_python_type_to_variable_type(
248
275
  element_type_annotation = args[0]
249
276
  # Recursively map the element type
250
277
  element_type = _map_python_type_to_variable_type(
251
- element_type_annotation, custom_types
278
+ element_type_annotation,
279
+ custom_type_registry,
280
+ custom_type_models,
252
281
  )
253
282
  # Support lists of both primitive types and custom types
254
283
  if isinstance(element_type, PrimitiveTypeEnum):
@@ -281,7 +310,9 @@ def _map_python_type_to_variable_type(
281
310
  return python_type.__name__
282
311
  elif inspect.isclass(python_type) and issubclass(python_type, BaseModel):
283
312
  # If it's a Pydantic model, create or retrieve its CustomType definition
284
- return _pydantic_to_custom_types(python_type, custom_types)
313
+ return _pydantic_to_custom_types(
314
+ python_type, custom_type_registry, custom_type_models
315
+ )
285
316
  raise ValueError(
286
317
  f"Unsupported Python type '{python_type}' for VariableType mapping"
287
318
  )
@@ -289,9 +320,12 @@ def _map_python_type_to_variable_type(
289
320
 
290
321
  def _map_python_type_to_type_str(
291
322
  python_type: Any,
292
- custom_types: dict[str, CustomType],
323
+ custom_type_registry: dict[str, Type[BaseModel]],
324
+ custom_type_models: dict[str, CustomType],
293
325
  ) -> str:
294
- var_type = _map_python_type_to_variable_type(python_type, custom_types)
326
+ var_type = _map_python_type_to_variable_type(
327
+ python_type, custom_type_registry, custom_type_models
328
+ )
295
329
  if isinstance(var_type, PrimitiveTypeEnum):
296
330
  return var_type.value
297
331
  elif inspect.isclass(python_type):
@@ -2,24 +2,48 @@ import argparse
2
2
  import json
3
3
  import logging
4
4
  from pathlib import Path
5
- from typing import Optional
5
+ from typing import Any, Optional
6
6
 
7
7
  from qtype.dsl.model import Document
8
8
 
9
9
  logger = logging.getLogger(__name__)
10
10
 
11
11
 
12
+ def generate_aws_bedrock_models() -> list[dict[str, Any]]:
13
+ """Generate AWS Bedrock model definitions.
14
+
15
+ Returns:
16
+ List of model definitions for AWS Bedrock models.
17
+
18
+ Raises:
19
+ ImportError: If boto3 is not installed.
20
+ Exception: If AWS API call fails.
21
+ """
22
+ import boto3 # type: ignore[import-untyped]
23
+
24
+ logger.info("Discovering AWS Bedrock models...")
25
+ client = boto3.client("bedrock")
26
+ models = client.list_foundation_models()
27
+
28
+ model_definitions = []
29
+ for model_summary in models.get("modelSummaries", []):
30
+ model_definitions.append(
31
+ {
32
+ "id": model_summary["modelId"],
33
+ "provider": "aws-bedrock",
34
+ }
35
+ )
36
+
37
+ logger.info(f"Discovered {len(model_definitions)} AWS Bedrock models")
38
+ return model_definitions
39
+
40
+
12
41
  def run_dump_commons_library(args: argparse.Namespace) -> None:
13
42
  """Generate commons library tools and AWS Bedrock models."""
14
- import logging
15
43
  from pathlib import Path
16
44
 
17
- from qtype.application.facade import QTypeFacade
18
45
  from qtype.dsl.model import Model, ModelList
19
46
 
20
- logger = logging.getLogger(__name__)
21
- facade = QTypeFacade()
22
-
23
47
  try:
24
48
  # Generate common tools using convert module functionality
25
49
  logger.info("Generating common tools...")
@@ -38,7 +62,7 @@ def run_dump_commons_library(args: argparse.Namespace) -> None:
38
62
  # Generate AWS Bedrock models
39
63
  logger.info("Generating AWS Bedrock models...")
40
64
  try:
41
- model_definitions = facade.generate_aws_bedrock_models()
65
+ model_definitions = generate_aws_bedrock_models()
42
66
 
43
67
  model_list = ModelList(
44
68
  root=[
@@ -80,6 +104,51 @@ def run_generate_documentation(args: argparse.Namespace) -> None:
80
104
  generate_documentation(Path(args.output))
81
105
 
82
106
 
107
+ def _copy_resource_file(resource, rel_path: Path, output_file: Path) -> None:
108
+ """Copy a file from a resource directory to an output location."""
109
+ content = resource.get_file(str(rel_path))
110
+ output_file.parent.mkdir(parents=True, exist_ok=True)
111
+ output_file.write_text(content, encoding="utf-8")
112
+
113
+
114
+ def run_generate_skill(args: argparse.Namespace) -> None:
115
+ """Generate a Claude skill with QType documentation and examples.
116
+
117
+ Args:
118
+ args: Command-line arguments with 'output' path.
119
+ """
120
+ from qtype.mcp.server import _docs_resource, _examples_resource
121
+
122
+ output_path = Path(args.output) / "qtype-architect"
123
+
124
+ # Copy skill documentation files
125
+ skills_path = _docs_resource.get_path() / "skills" / "architect"
126
+ skill_count = 0
127
+ for skill_file in skills_path.rglob("*.*"):
128
+ rel_path = skill_file.relative_to(_docs_resource.get_path())
129
+ _copy_resource_file(
130
+ _docs_resource,
131
+ rel_path,
132
+ output_path / rel_path.relative_to("skills/architect"),
133
+ )
134
+ skill_count += 1
135
+
136
+ # Copy all example files
137
+ example_count = 0
138
+ for yaml_file in _examples_resource.get_path().rglob("*.yaml"):
139
+ rel_path = yaml_file.relative_to(_examples_resource.get_path())
140
+ if "legacy" not in rel_path.parts:
141
+ _copy_resource_file(
142
+ _examples_resource, rel_path, output_path / "assets" / rel_path
143
+ )
144
+ example_count += 1
145
+
146
+ logger.info(
147
+ f"Skill generated at {output_path}: "
148
+ f"{skill_count} docs, {example_count} examples"
149
+ )
150
+
151
+
83
152
  def generate_schema(args: argparse.Namespace) -> None:
84
153
  """Generate and output the JSON schema for Document.
85
154
 
@@ -184,6 +253,20 @@ def parser(subparsers: argparse._SubParsersAction) -> None:
184
253
  )
185
254
  dsl_parser.set_defaults(func=run_generate_documentation)
186
255
 
256
+ # Parser for generating Agent skills
257
+ skill_parser = generate_subparsers.add_parser(
258
+ "skills",
259
+ help="Generates Agent skills with QType documentation and examples.",
260
+ )
261
+ skill_parser.add_argument(
262
+ "-o",
263
+ "--output",
264
+ type=str,
265
+ default=".claude/skills",
266
+ help="Output directory for the skills (default: .claude/skills)",
267
+ )
268
+ skill_parser.set_defaults(func=run_generate_skill)
269
+
187
270
  # Parser for generating the semantic model
188
271
  # only add this if networkx and ruff are installed
189
272
  try: