quantum-framework 0.18.0__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 (333) hide show
  1. quantum/__init__.py +1 -0
  2. quantum/cli/__init__.py +2 -0
  3. quantum/cli/admin.py +131 -0
  4. quantum/cli/check.py +223 -0
  5. quantum/cli/commands/__init__.py +15 -0
  6. quantum/cli/commands/build.py +414 -0
  7. quantum/cli/commands/dev.py +185 -0
  8. quantum/cli/commands/docs.py +329 -0
  9. quantum/cli/commands/lint.py +523 -0
  10. quantum/cli/commands/migrate.py +548 -0
  11. quantum/cli/commands/new.py +622 -0
  12. quantum/cli/commands/serve.py +190 -0
  13. quantum/cli/commands/test.py +193 -0
  14. quantum/cli/deploy.py +810 -0
  15. quantum/cli/hot_reload.py +951 -0
  16. quantum/cli/jobs.py +356 -0
  17. quantum/cli/mq.py +582 -0
  18. quantum/cli/pkg.py +390 -0
  19. quantum/cli/runner.py +565 -0
  20. quantum/cli/server_process.py +159 -0
  21. quantum/cli/utils.py +334 -0
  22. quantum/compiler/__init__.py +30 -0
  23. quantum/compiler/base_generator.py +367 -0
  24. quantum/compiler/cli.py +295 -0
  25. quantum/compiler/expression_transformer.py +444 -0
  26. quantum/compiler/javascript/__init__.py +10 -0
  27. quantum/compiler/javascript/generator.py +659 -0
  28. quantum/compiler/optimizer.py +270 -0
  29. quantum/compiler/python/__init__.py +10 -0
  30. quantum/compiler/python/generator.py +883 -0
  31. quantum/compiler/python/runtime.py +863 -0
  32. quantum/compiler/transpiler.py +330 -0
  33. quantum/core/__init__.py +3 -0
  34. quantum/core/ast_nodes.py +2619 -0
  35. quantum/core/config_env.py +54 -0
  36. quantum/core/docs_links.py +8 -0
  37. quantum/core/expression_diagnostics.py +87 -0
  38. quantum/core/expression_stdlib.py +208 -0
  39. quantum/core/expressions.py +677 -0
  40. quantum/core/features/agents/src/__init__.py +30 -0
  41. quantum/core/features/agents/src/ast_node.py +540 -0
  42. quantum/core/features/conditionals/src/__init__.py +8 -0
  43. quantum/core/features/conditionals/src/ast_node.py +68 -0
  44. quantum/core/features/data_import/src/__init__.py +0 -0
  45. quantum/core/features/data_import/src/ast_node.py +292 -0
  46. quantum/core/features/data_import/src/runtime.py +533 -0
  47. quantum/core/features/dump/src/__init__.py +12 -0
  48. quantum/core/features/dump/src/ast_node.py +106 -0
  49. quantum/core/features/dump/src/parser.py +61 -0
  50. quantum/core/features/dump/src/runtime.py +246 -0
  51. quantum/core/features/functions/src/__init__.py +8 -0
  52. quantum/core/features/functions/src/ast_node.py +149 -0
  53. quantum/core/features/game_engine_2d/src/__init__.py +19 -0
  54. quantum/core/features/game_engine_2d/src/ast_nodes.py +1719 -0
  55. quantum/core/features/game_engine_2d/src/parser.py +983 -0
  56. quantum/core/features/invocation/src/__init__.py +0 -0
  57. quantum/core/features/invocation/src/ast_node.py +147 -0
  58. quantum/core/features/invocation/src/runtime.py +332 -0
  59. quantum/core/features/knowledge_base/src/__init__.py +6 -0
  60. quantum/core/features/knowledge_base/src/ast_node.py +113 -0
  61. quantum/core/features/knowledge_base/src/parser.py +82 -0
  62. quantum/core/features/logging/src/__init__.py +12 -0
  63. quantum/core/features/logging/src/ast_node.py +111 -0
  64. quantum/core/features/logging/src/parser.py +50 -0
  65. quantum/core/features/logging/src/runtime.py +190 -0
  66. quantum/core/features/loops/src/__init__.py +8 -0
  67. quantum/core/features/loops/src/ast_node.py +60 -0
  68. quantum/core/features/query/src/__init__.py +0 -0
  69. quantum/core/features/query/src/query_validators.py +20 -0
  70. quantum/core/features/state_management/src/__init__.py +11 -0
  71. quantum/core/features/state_management/src/ast_node.py +121 -0
  72. quantum/core/features/terminal_engine/src/__init__.py +21 -0
  73. quantum/core/features/terminal_engine/src/ast_nodes.py +560 -0
  74. quantum/core/features/terminal_engine/src/parser.py +361 -0
  75. quantum/core/features/testing_engine/src/__init__.py +41 -0
  76. quantum/core/features/testing_engine/src/ast_nodes.py +1212 -0
  77. quantum/core/features/testing_engine/src/parser.py +604 -0
  78. quantum/core/features/theming/src/__init__.py +48 -0
  79. quantum/core/features/theming/src/ast_node.py +137 -0
  80. quantum/core/features/theming/src/presets.py +405 -0
  81. quantum/core/features/ui_engine/src/__init__.py +20 -0
  82. quantum/core/features/ui_engine/src/ast_nodes.py +1913 -0
  83. quantum/core/features/ui_engine/src/parser.py +1192 -0
  84. quantum/core/features/websocket/src/__init__.py +24 -0
  85. quantum/core/features/websocket/src/ast_node.py +247 -0
  86. quantum/core/guards.py +53 -0
  87. quantum/core/html_compat.py +299 -0
  88. quantum/core/parser.py +1551 -0
  89. quantum/core/parser_registry.py +213 -0
  90. quantum/core/parsers/__init__.py +76 -0
  91. quantum/core/parsers/ai/__init__.py +12 -0
  92. quantum/core/parsers/ai/agent_parser.py +106 -0
  93. quantum/core/parsers/ai/knowledge_parser.py +86 -0
  94. quantum/core/parsers/ai/llm_parser.py +78 -0
  95. quantum/core/parsers/ai/team_parser.py +88 -0
  96. quantum/core/parsers/base.py +322 -0
  97. quantum/core/parsers/composition/__init__.py +10 -0
  98. quantum/core/parsers/composition/import_parser.py +50 -0
  99. quantum/core/parsers/composition/slot_parser.py +48 -0
  100. quantum/core/parsers/control_flow/__init__.py +11 -0
  101. quantum/core/parsers/control_flow/if_parser.py +71 -0
  102. quantum/core/parsers/control_flow/loop_parser.py +105 -0
  103. quantum/core/parsers/control_flow/set_parser.py +93 -0
  104. quantum/core/parsers/data/__init__.py +12 -0
  105. quantum/core/parsers/data/data_parser.py +229 -0
  106. quantum/core/parsers/data/invoke_parser.py +133 -0
  107. quantum/core/parsers/data/query_parser.py +213 -0
  108. quantum/core/parsers/data/transaction_parser.py +86 -0
  109. quantum/core/parsers/events/__init__.py +9 -0
  110. quantum/core/parsers/events/dispatch_event_parser.py +44 -0
  111. quantum/core/parsers/forms/__init__.py +11 -0
  112. quantum/core/parsers/forms/action_parser.py +79 -0
  113. quantum/core/parsers/forms/flash_parser.py +34 -0
  114. quantum/core/parsers/forms/redirect_parser.py +33 -0
  115. quantum/core/parsers/functions/__init__.py +11 -0
  116. quantum/core/parsers/functions/function_parser.py +98 -0
  117. quantum/core/parsers/functions/param_parser.py +73 -0
  118. quantum/core/parsers/functions/return_parser.py +31 -0
  119. quantum/core/parsers/html/__init__.py +10 -0
  120. quantum/core/parsers/html/component_call_parser.py +130 -0
  121. quantum/core/parsers/html/html_parser.py +115 -0
  122. quantum/core/parsers/jobs/__init__.py +11 -0
  123. quantum/core/parsers/jobs/job_parser.py +71 -0
  124. quantum/core/parsers/jobs/schedule_parser.py +62 -0
  125. quantum/core/parsers/jobs/thread_parser.py +57 -0
  126. quantum/core/parsers/messaging/__init__.py +17 -0
  127. quantum/core/parsers/messaging/message_ack_parser.py +30 -0
  128. quantum/core/parsers/messaging/message_nack_parser.py +30 -0
  129. quantum/core/parsers/messaging/message_parser.py +114 -0
  130. quantum/core/parsers/messaging/queue_parser.py +61 -0
  131. quantum/core/parsers/messaging/websocket_parser.py +121 -0
  132. quantum/core/parsers/routing/__init__.py +9 -0
  133. quantum/core/parsers/routing/route_parser.py +41 -0
  134. quantum/core/parsers/scripting/__init__.py +12 -0
  135. quantum/core/parsers/scripting/pyclass_parser.py +62 -0
  136. quantum/core/parsers/scripting/pydecorator_parser.py +68 -0
  137. quantum/core/parsers/scripting/pyimport_parser.py +52 -0
  138. quantum/core/parsers/scripting/python_parser.py +49 -0
  139. quantum/core/parsers/services/__init__.py +12 -0
  140. quantum/core/parsers/services/dump_parser.py +52 -0
  141. quantum/core/parsers/services/file_parser.py +48 -0
  142. quantum/core/parsers/services/log_parser.py +46 -0
  143. quantum/core/parsers/services/mail_parser.py +65 -0
  144. quantum/core/tiers.py +164 -0
  145. quantum/core/xml_lines.py +81 -0
  146. quantum/packages/__init__.py +28 -0
  147. quantum/packages/manager.py +413 -0
  148. quantum/packages/manifest.py +351 -0
  149. quantum/packages/registry.py +399 -0
  150. quantum/packages/resolver.py +336 -0
  151. quantum/plugins/__init__.py +33 -0
  152. quantum/plugins/hooks.py +329 -0
  153. quantum/plugins/loader.py +479 -0
  154. quantum/plugins/manifest.py +336 -0
  155. quantum/plugins/registry.py +371 -0
  156. quantum/runtime/__init__.py +25 -0
  157. quantum/runtime/action_handler.py +532 -0
  158. quantum/runtime/adapters/__init__.py +88 -0
  159. quantum/runtime/adapters/memory_adapter.py +690 -0
  160. quantum/runtime/adapters/rabbitmq_adapter.py +715 -0
  161. quantum/runtime/adapters/redis_adapter.py +582 -0
  162. quantum/runtime/adapters/sqlite_adapter.py +414 -0
  163. quantum/runtime/agent_service.py +1133 -0
  164. quantum/runtime/ast_cache.py +506 -0
  165. quantum/runtime/auth_service.py +267 -0
  166. quantum/runtime/component.py +1048 -0
  167. quantum/runtime/component_composer.py +133 -0
  168. quantum/runtime/component_resolver.py +174 -0
  169. quantum/runtime/conditions.py +54 -0
  170. quantum/runtime/database_service.py +595 -0
  171. quantum/runtime/db_schema.py +100 -0
  172. quantum/runtime/dev_panel.py +178 -0
  173. quantum/runtime/email_service.py +162 -0
  174. quantum/runtime/error_handler.py +295 -0
  175. quantum/runtime/execution_context.py +283 -0
  176. quantum/runtime/executor_registry.py +178 -0
  177. quantum/runtime/executors/__init__.py +71 -0
  178. quantum/runtime/executors/ai/__init__.py +12 -0
  179. quantum/runtime/executors/ai/agent_executor.py +217 -0
  180. quantum/runtime/executors/ai/knowledge_executor.py +114 -0
  181. quantum/runtime/executors/ai/llm_executor.py +153 -0
  182. quantum/runtime/executors/ai/team_executor.py +171 -0
  183. quantum/runtime/executors/base.py +264 -0
  184. quantum/runtime/executors/control_flow/__init__.py +12 -0
  185. quantum/runtime/executors/control_flow/if_executor.py +98 -0
  186. quantum/runtime/executors/control_flow/loop_executor.py +308 -0
  187. quantum/runtime/executors/control_flow/redirect_executor.py +43 -0
  188. quantum/runtime/executors/control_flow/set_executor.py +464 -0
  189. quantum/runtime/executors/data/__init__.py +12 -0
  190. quantum/runtime/executors/data/data_executor.py +156 -0
  191. quantum/runtime/executors/data/invoke_executor.py +228 -0
  192. quantum/runtime/executors/data/query_executor.py +290 -0
  193. quantum/runtime/executors/data/transaction_executor.py +91 -0
  194. quantum/runtime/executors/jobs/__init__.py +11 -0
  195. quantum/runtime/executors/jobs/job_executor.py +190 -0
  196. quantum/runtime/executors/jobs/schedule_executor.py +132 -0
  197. quantum/runtime/executors/jobs/thread_executor.py +127 -0
  198. quantum/runtime/executors/messaging/__init__.py +17 -0
  199. quantum/runtime/executors/messaging/message_ack_executor.py +51 -0
  200. quantum/runtime/executors/messaging/message_executor.py +174 -0
  201. quantum/runtime/executors/messaging/queue_executor.py +103 -0
  202. quantum/runtime/executors/messaging/websocket_executor.py +197 -0
  203. quantum/runtime/executors/scripting/__init__.py +11 -0
  204. quantum/runtime/executors/scripting/pyclass_executor.py +90 -0
  205. quantum/runtime/executors/scripting/pyimport_executor.py +81 -0
  206. quantum/runtime/executors/scripting/python_executor.py +249 -0
  207. quantum/runtime/executors/services/__init__.py +12 -0
  208. quantum/runtime/executors/services/dump_executor.py +72 -0
  209. quantum/runtime/executors/services/file_executor.py +89 -0
  210. quantum/runtime/executors/services/log_executor.py +77 -0
  211. quantum/runtime/executors/services/mail_executor.py +81 -0
  212. quantum/runtime/expression_cache.py +498 -0
  213. quantum/runtime/file_upload_service.py +326 -0
  214. quantum/runtime/function_registry.py +118 -0
  215. quantum/runtime/game_builder.py +166 -0
  216. quantum/runtime/game_code_generator.py +2371 -0
  217. quantum/runtime/game_templates.py +2006 -0
  218. quantum/runtime/godot_code_generator.py +4681 -0
  219. quantum/runtime/godot_templates.py +1449 -0
  220. quantum/runtime/job_executor.py +1599 -0
  221. quantum/runtime/knowledge_service.py +546 -0
  222. quantum/runtime/llm_cache.py +100 -0
  223. quantum/runtime/llm_providers.py +704 -0
  224. quantum/runtime/llm_service.py +287 -0
  225. quantum/runtime/local_server.py +28 -0
  226. quantum/runtime/logging_setup.py +141 -0
  227. quantum/runtime/message_broker.py +364 -0
  228. quantum/runtime/message_queue_service.py +571 -0
  229. quantum/runtime/param_validation.py +218 -0
  230. quantum/runtime/pypy_compat.py +317 -0
  231. quantum/runtime/python_bridge.py +698 -0
  232. quantum/runtime/query_validators.py +304 -0
  233. quantum/runtime/renderer.py +734 -0
  234. quantum/runtime/service_container.py +470 -0
  235. quantum/runtime/table_params.py +163 -0
  236. quantum/runtime/terminal_builder.py +76 -0
  237. quantum/runtime/terminal_code_generator.py +607 -0
  238. quantum/runtime/terminal_templates.py +243 -0
  239. quantum/runtime/testing_builder.py +77 -0
  240. quantum/runtime/testing_code_generator.py +833 -0
  241. quantum/runtime/testing_templates.py +85 -0
  242. quantum/runtime/ui_builder.py +222 -0
  243. quantum/runtime/ui_console.py +405 -0
  244. quantum/runtime/ui_desktop.py +56 -0
  245. quantum/runtime/ui_form_rules.py +193 -0
  246. quantum/runtime/ui_html_adapter.py +2567 -0
  247. quantum/runtime/ui_html_templates.py +2106 -0
  248. quantum/runtime/ui_mobile_adapter.py +1832 -0
  249. quantum/runtime/ui_mobile_templates.py +1003 -0
  250. quantum/runtime/ui_page_renderer.py +392 -0
  251. quantum/runtime/ui_pager.py +73 -0
  252. quantum/runtime/ui_table_edit.py +139 -0
  253. quantum/runtime/ui_textual_adapter.py +1866 -0
  254. quantum/runtime/ui_textual_templates.py +45 -0
  255. quantum/runtime/ui_tokens.py +465 -0
  256. quantum/runtime/ui_validator.py +365 -0
  257. quantum/runtime/ui_view.py +221 -0
  258. quantum/runtime/validators.py +256 -0
  259. quantum/runtime/web_server.py +2131 -0
  260. quantum/runtime/websocket_adapter.py +501 -0
  261. quantum/runtime/websocket_service.py +585 -0
  262. quantum/runtime/websocket_transport.py +289 -0
  263. quantum/runtime/wsgi.py +101 -0
  264. quantum/services.py +109 -0
  265. quantum/utils/__init__.py +1 -0
  266. quantum_admin/__init__.py +4 -0
  267. quantum_admin/assets/quantum-admin-connectors.js +123 -0
  268. quantum_admin/assets/quantum-admin.css +2058 -0
  269. quantum_admin/assets/quantum-source-highlight.js +106 -0
  270. quantum_admin/backend/__init__.py +4 -0
  271. quantum_admin/backend/audit_service.py +346 -0
  272. quantum_admin/backend/auth_service.py +394 -0
  273. quantum_admin/backend/component_discovery.py +766 -0
  274. quantum_admin/backend/config_generator.py +586 -0
  275. quantum_admin/backend/connector_service.py +1016 -0
  276. quantum_admin/backend/crud.py +557 -0
  277. quantum_admin/backend/database.py +226 -0
  278. quantum_admin/backend/db_setup_service.py +193 -0
  279. quantum_admin/backend/deploy_service.py +698 -0
  280. quantum_admin/backend/docker_service.py +422 -0
  281. quantum_admin/backend/environment_service.py +418 -0
  282. quantum_admin/backend/git_service.py +370 -0
  283. quantum_admin/backend/health_service.py +390 -0
  284. quantum_admin/backend/job_service.py +347 -0
  285. quantum_admin/backend/log_service.py +331 -0
  286. quantum_admin/backend/main.py +14426 -0
  287. quantum_admin/backend/models.py +986 -0
  288. quantum_admin/backend/pipeline_service.py +812 -0
  289. quantum_admin/backend/resource_manager.py +1118 -0
  290. quantum_admin/backend/schemas.py +419 -0
  291. quantum_admin/backend/secret_manager.py +277 -0
  292. quantum_admin/backend/settings_service.py +488 -0
  293. quantum_admin/backend/template_service.py +710 -0
  294. quantum_admin/backend/test_execution_service.py +364 -0
  295. quantum_admin/backend/test_generator.py +782 -0
  296. quantum_admin/backend/webhook_service.py +454 -0
  297. quantum_admin/backend/websocket_manager.py +360 -0
  298. quantum_admin/components/admin/_layout/AdminShell.q +121 -0
  299. quantum_admin/components/admin/agents.q +107 -0
  300. quantum_admin/components/admin/app/[name].q +558 -0
  301. quantum_admin/components/admin/applications.q +160 -0
  302. quantum_admin/components/admin/component/[...path].q +205 -0
  303. quantum_admin/components/admin/components.q +59 -0
  304. quantum_admin/components/admin/connectors.q +283 -0
  305. quantum_admin/components/admin/dashboard.q +86 -0
  306. quantum_admin/components/admin/database.q +95 -0
  307. quantum_admin/components/admin/features.q +69 -0
  308. quantum_admin/components/admin/index.q +12 -0
  309. quantum_admin/components/admin/jobs.q +75 -0
  310. quantum_admin/components/admin/login.q +65 -0
  311. quantum_admin/components/admin/logout.q +11 -0
  312. quantum_admin/components/admin/settings.q +174 -0
  313. quantum_admin/components/admin/source.q +45 -0
  314. quantum_admin/components/admin/tests.q +73 -0
  315. quantum_admin/run.py +13 -0
  316. quantum_admin/services/__init__.py +16 -0
  317. quantum_admin/services/_base.py +84 -0
  318. quantum_admin/services/_component_test_generator.py +205 -0
  319. quantum_admin/services/_yaml_editor.py +82 -0
  320. quantum_admin/services/apps.py +330 -0
  321. quantum_admin/services/auth.py +61 -0
  322. quantum_admin/services/components.py +210 -0
  323. quantum_admin/services/connectors.py +164 -0
  324. quantum_admin/services/projects.py +189 -0
  325. quantum_admin/services/repository.py +223 -0
  326. quantum_admin/services/settings.py +150 -0
  327. quantum_admin/services/yaml_import.py +118 -0
  328. quantum_framework-0.18.0.dist-info/METADATA +281 -0
  329. quantum_framework-0.18.0.dist-info/RECORD +333 -0
  330. quantum_framework-0.18.0.dist-info/WHEEL +5 -0
  331. quantum_framework-0.18.0.dist-info/entry_points.txt +2 -0
  332. quantum_framework-0.18.0.dist-info/licenses/LICENSE +21 -0
  333. quantum_framework-0.18.0.dist-info/top_level.txt +2 -0
@@ -0,0 +1,30 @@
1
+ """
2
+ Agents Feature - AI Agents with Tool Use
3
+
4
+ This module provides AST nodes for the q:agent feature,
5
+ enabling autonomous AI agents that can use tools to complete tasks.
6
+
7
+ Multi-Agent Systems:
8
+ - AgentTeamNode: Team of collaborating agents
9
+ - AgentHandoffNode: Built-in handoff tool for agent delegation
10
+ """
11
+
12
+ from .ast_node import (
13
+ AgentNode,
14
+ AgentInstructionNode,
15
+ AgentToolNode,
16
+ AgentToolParamNode,
17
+ AgentExecuteNode,
18
+ AgentTeamNode,
19
+ AgentHandoffNode,
20
+ )
21
+
22
+ __all__ = [
23
+ 'AgentNode',
24
+ 'AgentInstructionNode',
25
+ 'AgentToolNode',
26
+ 'AgentToolParamNode',
27
+ 'AgentExecuteNode',
28
+ 'AgentTeamNode',
29
+ 'AgentHandoffNode',
30
+ ]
@@ -0,0 +1,540 @@
1
+ """
2
+ Agent AST Nodes
3
+
4
+ Defines the AST structure for AI agents with tool use capabilities.
5
+
6
+ Classes:
7
+ AgentToolParamNode - Parameter definition for a tool
8
+ AgentToolNode - Tool available to the agent
9
+ AgentInstructionNode - System instruction for the agent
10
+ AgentExecuteNode - Execute the agent with a task
11
+ AgentNode - Main agent definition
12
+ AgentHandoffNode - Built-in handoff tool for agent delegation
13
+ AgentTeamNode - Team of collaborating agents
14
+ """
15
+
16
+ from dataclasses import dataclass, field
17
+ from typing import List, Optional, Any
18
+
19
+ # Import base class - handle both direct and package imports
20
+ try:
21
+ from quantum.core.ast_nodes import QuantumNode
22
+ except ImportError:
23
+ from ...ast_nodes import QuantumNode
24
+
25
+
26
+ @dataclass
27
+ class AgentToolParamNode(QuantumNode):
28
+ """
29
+ Parameter definition for an agent tool.
30
+
31
+ Attributes:
32
+ name: Parameter name (required)
33
+ type: Parameter type (string, integer, number, boolean, array, object)
34
+ required: Whether the parameter is required
35
+ default: Default value if not provided
36
+ description: Human-readable description for the LLM
37
+
38
+ Example:
39
+ <q:param name="orderId" type="integer" required="true"
40
+ description="The order ID to look up" />
41
+ """
42
+ name: str = ""
43
+ type: str = "string"
44
+ required: bool = False
45
+ default: Optional[Any] = None
46
+ description: str = ""
47
+
48
+ def to_dict(self) -> dict:
49
+ """Convert to dictionary."""
50
+ return {
51
+ "name": self.name,
52
+ "type": self.type,
53
+ "required": self.required,
54
+ "default": self.default,
55
+ "description": self.description
56
+ }
57
+
58
+ def validate(self) -> List[str]:
59
+ """Validate the parameter node."""
60
+ errors = []
61
+ if not self.name:
62
+ errors.append("AgentToolParamNode requires 'name' attribute")
63
+ valid_types = {"string", "integer", "number", "boolean", "array", "object", "date", "decimal"}
64
+ if self.type not in valid_types:
65
+ errors.append(f"Invalid param type '{self.type}'. Must be one of: {valid_types}")
66
+ return errors
67
+
68
+
69
+ @dataclass
70
+ class AgentToolNode(QuantumNode):
71
+ """
72
+ Tool available to the agent.
73
+
74
+ A tool is a function that the agent can call to perform actions
75
+ or retrieve information. Tools have parameters and a body that
76
+ defines what happens when the tool is called.
77
+
78
+ Attributes:
79
+ name: Tool name (used by LLM to call it)
80
+ description: What the tool does (helps LLM decide when to use it)
81
+ params: List of parameter definitions
82
+ body: List of AST nodes to execute when tool is called
83
+ builtin: If True, this is a built-in tool (handoff, readShared, etc.)
84
+
85
+ Built-in Tools (use builtin="true"):
86
+ - handoff: Transfer to another agent in the team
87
+ - readShared: Read from shared team memory
88
+ - writeShared: Write to shared team memory
89
+ - listAgents: List available agents in the team
90
+
91
+ Example:
92
+ <q:tool name="getOrder" description="Get order details by ID">
93
+ <q:param name="orderId" type="integer" required="true" />
94
+ <q:function name="fetchOrder">
95
+ <q:query name="order" datasource="db">
96
+ SELECT * FROM orders WHERE id = :orderId
97
+ </q:query>
98
+ <q:return value="{order[0]}" />
99
+ </q:function>
100
+ </q:tool>
101
+
102
+ <!-- Built-in tool -->
103
+ <q:tool name="handoff" builtin="true" />
104
+ """
105
+ name: str = ""
106
+ description: str = ""
107
+ params: List[AgentToolParamNode] = field(default_factory=list)
108
+ body: List[QuantumNode] = field(default_factory=list)
109
+ builtin: bool = False # True for built-in tools like handoff, readShared
110
+
111
+ def to_dict(self) -> dict:
112
+ """Convert to dictionary."""
113
+ return {
114
+ "name": self.name,
115
+ "description": self.description,
116
+ "params": [p.to_dict() for p in self.params],
117
+ "body": [b.to_dict() if hasattr(b, 'to_dict') else str(b) for b in self.body],
118
+ "builtin": self.builtin
119
+ }
120
+
121
+ def validate(self) -> List[str]:
122
+ """Validate the tool node."""
123
+ errors = []
124
+ if not self.name:
125
+ errors.append("AgentToolNode requires 'name' attribute")
126
+ # Built-in tools get their description automatically
127
+ if not self.description and not self.builtin:
128
+ errors.append(f"Tool '{self.name}' should have a description for the LLM")
129
+ for param in self.params:
130
+ errors.extend(param.validate())
131
+ return errors
132
+
133
+ def is_builtin(self) -> bool:
134
+ """Check if this is a built-in tool."""
135
+ return self.builtin
136
+
137
+ def get_schema(self) -> dict:
138
+ """Get JSON Schema representation for LLM tool calling."""
139
+ properties = {}
140
+ required = []
141
+
142
+ for param in self.params:
143
+ prop = {"type": self._map_type(param.type)}
144
+ if param.description:
145
+ prop["description"] = param.description
146
+ if param.default is not None:
147
+ prop["default"] = param.default
148
+ properties[param.name] = prop
149
+
150
+ if param.required:
151
+ required.append(param.name)
152
+
153
+ return {
154
+ "name": self.name,
155
+ "description": self.description,
156
+ "parameters": {
157
+ "type": "object",
158
+ "properties": properties,
159
+ "required": required
160
+ }
161
+ }
162
+
163
+ def _map_type(self, quantum_type: str) -> str:
164
+ """Map Quantum types to JSON Schema types."""
165
+ type_map = {
166
+ "string": "string",
167
+ "integer": "integer",
168
+ "number": "number",
169
+ "decimal": "number",
170
+ "boolean": "boolean",
171
+ "array": "array",
172
+ "object": "object",
173
+ "date": "string",
174
+ }
175
+ return type_map.get(quantum_type, "string")
176
+
177
+
178
+ @dataclass
179
+ class AgentInstructionNode(QuantumNode):
180
+ """
181
+ System instruction for the agent.
182
+
183
+ Defines the agent's role, personality, and behavior guidelines.
184
+ This becomes part of the system prompt sent to the LLM.
185
+
186
+ Attributes:
187
+ content: The instruction text (supports databinding)
188
+
189
+ Example:
190
+ <q:instruction>
191
+ You are a helpful customer support agent.
192
+ Be polite, concise, and helpful.
193
+ Always verify information before taking action.
194
+ </q:instruction>
195
+ """
196
+ content: str = ""
197
+
198
+ def to_dict(self) -> dict:
199
+ """Convert to dictionary."""
200
+ return {"content": self.content}
201
+
202
+ def validate(self) -> List[str]:
203
+ """Validate the instruction node."""
204
+ errors = []
205
+ if not self.content.strip():
206
+ errors.append("AgentInstructionNode should have content")
207
+ return errors
208
+
209
+
210
+ @dataclass
211
+ class AgentExecuteNode(QuantumNode):
212
+ """
213
+ Execute the agent with a specific task.
214
+
215
+ Triggers the agent's reasoning loop to complete the given task
216
+ using the available tools.
217
+
218
+ Attributes:
219
+ task: The task/question for the agent (supports databinding)
220
+ context: Additional context to provide (optional, supports databinding)
221
+ entry: Entry agent name for team execution (optional)
222
+
223
+ Example:
224
+ <q:execute task="Check status of order #1234 and update if needed" />
225
+
226
+ <q:execute task="{userMessage}" context="User ID: {userId}" />
227
+
228
+ <!-- For team execution with specific entry point -->
229
+ <q:execute task="{question}" entry="router" />
230
+ """
231
+ task: str = ""
232
+ context: str = ""
233
+ entry: str = "" # Entry agent for team execution
234
+
235
+ def to_dict(self) -> dict:
236
+ """Convert to dictionary."""
237
+ result = {"task": self.task, "context": self.context}
238
+ if self.entry:
239
+ result["entry"] = self.entry
240
+ return result
241
+
242
+ def validate(self) -> List[str]:
243
+ """Validate the execute node."""
244
+ errors = []
245
+ if not self.task:
246
+ errors.append("AgentExecuteNode requires 'task' attribute or content")
247
+ return errors
248
+
249
+
250
+ @dataclass
251
+ class AgentNode(QuantumNode):
252
+ """
253
+ AI Agent that can use tools to complete tasks.
254
+
255
+ An agent is an autonomous AI that can:
256
+ 1. Receive a task from the user
257
+ 2. Reason about which tools to use
258
+ 3. Call tools to gather information or take actions
259
+ 4. Synthesize results into a coherent response
260
+
261
+ Attributes:
262
+ name: Variable name to store result (required)
263
+ model: LLM model identifier (default: "phi3")
264
+ endpoint: Custom LLM API endpoint (optional)
265
+ provider: LLM provider (ollama, openai, anthropic, auto)
266
+ api_key: API key for cloud providers (optional)
267
+ max_iterations: Maximum tool calls allowed (default: 10)
268
+ timeout: Total timeout in milliseconds (default: 60000)
269
+ instruction: System instruction/prompt
270
+ tools: List of available tools
271
+ execute: Task to execute
272
+
273
+ Result Object:
274
+ {name}: The agent's final response (string)
275
+ {name}_result: Full result object with:
276
+ - success: bool
277
+ - result: str
278
+ - error: {message: str} or None
279
+ - executionTime: float (ms)
280
+ - iterations: int
281
+ - actionCount: int
282
+ - actions: [{tool, args, result}, ...]
283
+ - tokenUsage: {prompt, completion, total}
284
+
285
+ Supported Providers:
286
+ - ollama: Local Ollama server (default: http://localhost:11434)
287
+ - openai: OpenAI API or LM Studio (http://localhost:1234/v1)
288
+ - anthropic: Anthropic Claude API
289
+ - auto: Auto-detect from endpoint
290
+
291
+ Example:
292
+ <!-- Using Ollama (default) -->
293
+ <q:agent name="support" model="phi3" max_iterations="5">
294
+ ...
295
+ </q:agent>
296
+
297
+ <!-- Using OpenAI -->
298
+ <q:agent name="helper" model="gpt-4" provider="openai"
299
+ api_key="{env.OPENAI_API_KEY}">
300
+ ...
301
+ </q:agent>
302
+
303
+ <!-- Using LM Studio -->
304
+ <q:agent name="local" model="mistral"
305
+ endpoint="http://localhost:1234/v1">
306
+ ...
307
+ </q:agent>
308
+
309
+ <!-- Using Claude -->
310
+ <q:agent name="claude" model="claude-3-haiku-20240307"
311
+ provider="anthropic" api_key="{env.ANTHROPIC_API_KEY}">
312
+ ...
313
+ </q:agent>
314
+ """
315
+ name: str = ""
316
+ model: str = "phi3"
317
+ endpoint: str = ""
318
+ provider: str = "auto" # ollama, openai, anthropic, auto
319
+ api_key: str = "" # For cloud providers
320
+ max_iterations: int = 10
321
+ timeout: int = 60000 # milliseconds
322
+
323
+ instruction: Optional[AgentInstructionNode] = None
324
+ tools: List[AgentToolNode] = field(default_factory=list)
325
+ execute: Optional[AgentExecuteNode] = None
326
+
327
+ # Set by the team parser for agents declared inside <q:team>. Those agents
328
+ # are driven by the team's own <q:execute>, so requiring one of their own
329
+ # would reject every valid team component.
330
+ in_team: bool = False
331
+
332
+ def to_dict(self) -> dict:
333
+ """Convert to dictionary."""
334
+ return {
335
+ "name": self.name,
336
+ "model": self.model,
337
+ "endpoint": self.endpoint,
338
+ "provider": self.provider,
339
+ "api_key": self.api_key,
340
+ "max_iterations": self.max_iterations,
341
+ "timeout": self.timeout,
342
+ "instruction": self.instruction.to_dict() if self.instruction else None,
343
+ "tools": [t.to_dict() for t in self.tools],
344
+ "execute": self.execute.to_dict() if self.execute else None
345
+ }
346
+
347
+ def validate(self) -> List[str]:
348
+ """Validate the agent node."""
349
+ errors = []
350
+
351
+ if not self.name:
352
+ errors.append("AgentNode requires 'name' attribute")
353
+
354
+ if not self.model:
355
+ errors.append("AgentNode requires 'model' attribute")
356
+
357
+ if self.max_iterations < 1:
358
+ errors.append("max_iterations must be at least 1")
359
+
360
+ if self.max_iterations > 100:
361
+ errors.append("max_iterations should not exceed 100 for safety")
362
+
363
+ if self.timeout < 1000:
364
+ errors.append("timeout should be at least 1000ms (1 second)")
365
+
366
+ if not self.tools:
367
+ errors.append("AgentNode should have at least one tool")
368
+
369
+ if not self.execute and not self.in_team:
370
+ errors.append("AgentNode requires <q:execute> to run")
371
+
372
+ # Validate children
373
+ if self.instruction:
374
+ errors.extend(self.instruction.validate())
375
+
376
+ for tool in self.tools:
377
+ errors.extend(tool.validate())
378
+
379
+ if self.execute:
380
+ errors.extend(self.execute.validate())
381
+
382
+ return errors
383
+
384
+ def get_tools_schema(self) -> List[dict]:
385
+ """Get JSON Schema for all tools (for LLM function calling)."""
386
+ return [tool.get_schema() for tool in self.tools]
387
+
388
+
389
+ @dataclass
390
+ class AgentHandoffNode(QuantumNode):
391
+ """
392
+ Built-in handoff tool for agent delegation.
393
+
394
+ Allows an agent to transfer control to another agent in a team,
395
+ passing along context and the current task state.
396
+
397
+ Attributes:
398
+ target_agent: Name of the agent to hand off to
399
+ context: Additional context/message for the target agent
400
+
401
+ Example (used internally when agent calls handoff tool):
402
+ {"action": "handoff", "args": {"agent": "billing", "message": "Customer needs invoice help"}}
403
+ """
404
+ target_agent: str = ""
405
+ context: str = ""
406
+
407
+ def to_dict(self) -> dict:
408
+ """Convert to dictionary."""
409
+ return {
410
+ "target_agent": self.target_agent,
411
+ "context": self.context
412
+ }
413
+
414
+ def validate(self) -> List[str]:
415
+ """Validate the handoff node."""
416
+ errors = []
417
+ if not self.target_agent:
418
+ errors.append("AgentHandoffNode requires 'target_agent'")
419
+ return errors
420
+
421
+
422
+ @dataclass
423
+ class AgentTeamNode(QuantumNode):
424
+ """
425
+ Team of collaborating agents that can hand off tasks to each other.
426
+
427
+ A team provides:
428
+ 1. Shared context accessible by all agents
429
+ 2. Agent discovery and handoff capabilities
430
+ 3. Orchestration with entry point and handoff limits
431
+
432
+ Attributes:
433
+ name: Team name (used to store results)
434
+ supervisor: Entry agent name (default entry point)
435
+ shared: List of SetNode for shared state initialization
436
+ agents: List of AgentNode team members
437
+ execute: AgentExecuteNode with task and optional entry agent
438
+ max_handoffs: Maximum handoffs allowed (safety limit, default 10)
439
+ max_total_iterations: Sum of all agent iterations (default 50)
440
+
441
+ Result Object:
442
+ {name}: The final agent's response (string)
443
+ {name}_result: Full result object with:
444
+ - success: bool
445
+ - finalResponse: str
446
+ - finalAgent: str
447
+ - handoffs: [{fromAgent, toAgent, message, timestamp}, ...]
448
+ - totalIterations: int
449
+ - executionTime: float (ms)
450
+ - agentResults: {agentName: AgentResult, ...}
451
+ - sharedContext: {key: value, ...}
452
+
453
+ Example:
454
+ <q:team name="support" supervisor="router">
455
+ <q:shared>
456
+ <q:set name="customerName" value="John" />
457
+ </q:shared>
458
+
459
+ <q:agent name="router" model="gpt-4">
460
+ <q:instruction>Route to appropriate specialist</q:instruction>
461
+ <q:tool name="handoff" builtin="true" />
462
+ </q:agent>
463
+
464
+ <q:agent name="billing" model="gpt-4">
465
+ <q:instruction>Handle billing questions</q:instruction>
466
+ <q:tool name="readShared" builtin="true" />
467
+ </q:agent>
468
+
469
+ <q:execute task="{question}" entry="router" />
470
+ </q:team>
471
+ """
472
+ name: str = ""
473
+ supervisor: str = "" # Entry agent (default)
474
+ shared: List[Any] = field(default_factory=list) # SetNode list
475
+ agents: List['AgentNode'] = field(default_factory=list)
476
+ execute: Optional[AgentExecuteNode] = None
477
+ max_handoffs: int = 10 # Safety limit for handoffs
478
+ max_total_iterations: int = 50 # Total iterations across all agents
479
+
480
+ def to_dict(self) -> dict:
481
+ """Convert to dictionary."""
482
+ return {
483
+ "name": self.name,
484
+ "supervisor": self.supervisor,
485
+ "shared": [s.to_dict() if hasattr(s, 'to_dict') else str(s) for s in self.shared],
486
+ "agents": [a.to_dict() for a in self.agents],
487
+ "execute": self.execute.to_dict() if self.execute else None,
488
+ "max_handoffs": self.max_handoffs,
489
+ "max_total_iterations": self.max_total_iterations
490
+ }
491
+
492
+ def validate(self) -> List[str]:
493
+ """Validate the team node."""
494
+ errors = []
495
+
496
+ if not self.name:
497
+ errors.append("AgentTeamNode requires 'name' attribute")
498
+
499
+ if not self.agents:
500
+ errors.append("AgentTeamNode requires at least one agent")
501
+
502
+ if not self.execute:
503
+ errors.append("AgentTeamNode requires <q:execute> to run")
504
+
505
+ # Validate supervisor exists in agents
506
+ agent_names = {a.name for a in self.agents}
507
+ if self.supervisor and self.supervisor not in agent_names:
508
+ errors.append(f"Supervisor '{self.supervisor}' not found in team agents: {agent_names}")
509
+
510
+ # Validate entry agent if specified in execute
511
+ if self.execute and hasattr(self.execute, 'entry'):
512
+ entry = getattr(self.execute, 'entry', None)
513
+ if entry and entry not in agent_names:
514
+ errors.append(f"Entry agent '{entry}' not found in team agents: {agent_names}")
515
+
516
+ if self.max_handoffs < 1:
517
+ errors.append("max_handoffs must be at least 1")
518
+
519
+ if self.max_handoffs > 100:
520
+ errors.append("max_handoffs should not exceed 100 for safety")
521
+
522
+ if self.max_total_iterations < 1:
523
+ errors.append("max_total_iterations must be at least 1")
524
+
525
+ # Validate child agents
526
+ for agent in self.agents:
527
+ errors.extend(agent.validate())
528
+
529
+ return errors
530
+
531
+ def get_agent(self, name: str) -> Optional['AgentNode']:
532
+ """Get an agent by name."""
533
+ for agent in self.agents:
534
+ if agent.name == name:
535
+ return agent
536
+ return None
537
+
538
+ def get_agent_names(self) -> List[str]:
539
+ """Get list of all agent names in the team."""
540
+ return [a.name for a in self.agents]
@@ -0,0 +1,8 @@
1
+ """
2
+ Conditionals Feature (q:if/q:else/q:elseif)
3
+ """
4
+
5
+ from .ast_node import IfNode
6
+
7
+ __all__ = ['IfNode']
8
+ __version__ = '1.0.0'
@@ -0,0 +1,68 @@
1
+ """
2
+ AST Node for Conditionals (q:if/q:else/q:elseif)
3
+ """
4
+
5
+ from typing import Dict, Any, List
6
+
7
+ # Import base class
8
+ import sys
9
+ from pathlib import Path
10
+ from quantum.core.ast_nodes import QuantumNode
11
+
12
+
13
+ class IfNode(QuantumNode):
14
+ """Represents a <q:if> with elseif and else"""
15
+
16
+ def __init__(self, condition: str):
17
+ self.condition = condition
18
+ self.if_body: List[QuantumNode] = []
19
+
20
+ # Support for elseif blocks
21
+ self.elseif_blocks: List[Dict[str, Any]] = [] # [{"condition": str, "body": List[QuantumNode]}]
22
+
23
+ # Support for else block
24
+ self.else_body: List[QuantumNode] = []
25
+
26
+ def add_if_statement(self, statement: QuantumNode):
27
+ """Add statement to if body"""
28
+ self.if_body.append(statement)
29
+
30
+ def add_elseif_block(self, condition: str, body: List[QuantumNode] = None):
31
+ """Add elseif block"""
32
+ self.elseif_blocks.append({
33
+ "condition": condition,
34
+ "body": body or []
35
+ })
36
+
37
+ def add_else_statement(self, statement: QuantumNode):
38
+ """Add statement to else body"""
39
+ self.else_body.append(statement)
40
+
41
+ def to_dict(self) -> Dict[str, Any]:
42
+ return {
43
+ "type": "if",
44
+ "condition": self.condition,
45
+ "if_body_count": len(self.if_body),
46
+ "elseif_count": len(self.elseif_blocks),
47
+ "has_else": len(self.else_body) > 0
48
+ }
49
+
50
+ def validate(self) -> List[str]:
51
+ errors = []
52
+ if not self.condition:
53
+ errors.append("If condition is required")
54
+
55
+ # Validate all bodies
56
+ for statement in self.if_body:
57
+ errors.extend(statement.validate())
58
+
59
+ for elseif_block in self.elseif_blocks:
60
+ if not elseif_block["condition"]:
61
+ errors.append("Elseif condition is required")
62
+ for statement in elseif_block["body"]:
63
+ errors.extend(statement.validate())
64
+
65
+ for statement in self.else_body:
66
+ errors.extend(statement.validate())
67
+
68
+ return errors
File without changes