quantum-framework 0.9.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 (262) hide show
  1. quantum/__init__.py +1 -0
  2. quantum/cli/__init__.py +2 -0
  3. quantum/cli/commands/__init__.py +15 -0
  4. quantum/cli/commands/build.py +417 -0
  5. quantum/cli/commands/dev.py +185 -0
  6. quantum/cli/commands/docs.py +329 -0
  7. quantum/cli/commands/lint.py +523 -0
  8. quantum/cli/commands/migrate.py +527 -0
  9. quantum/cli/commands/new.py +622 -0
  10. quantum/cli/commands/serve.py +190 -0
  11. quantum/cli/commands/test.py +193 -0
  12. quantum/cli/deploy.py +810 -0
  13. quantum/cli/hot_reload.py +951 -0
  14. quantum/cli/jobs.py +356 -0
  15. quantum/cli/mq.py +582 -0
  16. quantum/cli/pkg.py +390 -0
  17. quantum/cli/runner.py +547 -0
  18. quantum/cli/server_process.py +159 -0
  19. quantum/cli/utils.py +334 -0
  20. quantum/compiler/__init__.py +30 -0
  21. quantum/compiler/base_generator.py +367 -0
  22. quantum/compiler/cli.py +295 -0
  23. quantum/compiler/expression_transformer.py +444 -0
  24. quantum/compiler/javascript/__init__.py +10 -0
  25. quantum/compiler/javascript/generator.py +659 -0
  26. quantum/compiler/optimizer.py +270 -0
  27. quantum/compiler/python/__init__.py +10 -0
  28. quantum/compiler/python/generator.py +883 -0
  29. quantum/compiler/python/runtime.py +863 -0
  30. quantum/compiler/transpiler.py +330 -0
  31. quantum/core/__init__.py +3 -0
  32. quantum/core/ast_nodes.py +2611 -0
  33. quantum/core/expression_diagnostics.py +87 -0
  34. quantum/core/expression_stdlib.py +148 -0
  35. quantum/core/expressions.py +591 -0
  36. quantum/core/features/agents/src/__init__.py +30 -0
  37. quantum/core/features/agents/src/ast_node.py +540 -0
  38. quantum/core/features/conditionals/src/__init__.py +8 -0
  39. quantum/core/features/conditionals/src/ast_node.py +68 -0
  40. quantum/core/features/data_fetching/src/__init__.py +21 -0
  41. quantum/core/features/data_fetching/src/ast_node.py +312 -0
  42. quantum/core/features/data_fetching/src/desktop_adapter.py +351 -0
  43. quantum/core/features/data_fetching/src/html_adapter.py +474 -0
  44. quantum/core/features/data_fetching/src/parser.py +225 -0
  45. quantum/core/features/data_import/src/__init__.py +0 -0
  46. quantum/core/features/data_import/src/ast_node.py +291 -0
  47. quantum/core/features/data_import/src/runtime.py +538 -0
  48. quantum/core/features/dump/src/__init__.py +12 -0
  49. quantum/core/features/dump/src/ast_node.py +106 -0
  50. quantum/core/features/dump/src/parser.py +61 -0
  51. quantum/core/features/dump/src/runtime.py +246 -0
  52. quantum/core/features/functions/src/__init__.py +8 -0
  53. quantum/core/features/functions/src/ast_node.py +149 -0
  54. quantum/core/features/game_engine_2d/src/__init__.py +19 -0
  55. quantum/core/features/game_engine_2d/src/ast_nodes.py +1719 -0
  56. quantum/core/features/game_engine_2d/src/parser.py +983 -0
  57. quantum/core/features/invocation/src/__init__.py +0 -0
  58. quantum/core/features/invocation/src/ast_node.py +146 -0
  59. quantum/core/features/invocation/src/runtime.py +327 -0
  60. quantum/core/features/knowledge_base/src/__init__.py +6 -0
  61. quantum/core/features/knowledge_base/src/ast_node.py +113 -0
  62. quantum/core/features/knowledge_base/src/parser.py +82 -0
  63. quantum/core/features/logging/src/__init__.py +12 -0
  64. quantum/core/features/logging/src/ast_node.py +111 -0
  65. quantum/core/features/logging/src/parser.py +50 -0
  66. quantum/core/features/logging/src/runtime.py +190 -0
  67. quantum/core/features/loops/src/__init__.py +8 -0
  68. quantum/core/features/loops/src/ast_node.py +60 -0
  69. quantum/core/features/query/src/__init__.py +0 -0
  70. quantum/core/features/query/src/database_service.py +322 -0
  71. quantum/core/features/query/src/query_validators.py +20 -0
  72. quantum/core/features/state_management/src/__init__.py +11 -0
  73. quantum/core/features/state_management/src/ast_node.py +228 -0
  74. quantum/core/features/terminal_engine/src/__init__.py +21 -0
  75. quantum/core/features/terminal_engine/src/ast_nodes.py +560 -0
  76. quantum/core/features/terminal_engine/src/parser.py +361 -0
  77. quantum/core/features/testing_engine/src/__init__.py +41 -0
  78. quantum/core/features/testing_engine/src/ast_nodes.py +1212 -0
  79. quantum/core/features/testing_engine/src/parser.py +604 -0
  80. quantum/core/features/theming/src/__init__.py +48 -0
  81. quantum/core/features/theming/src/ast_node.py +137 -0
  82. quantum/core/features/theming/src/presets.py +405 -0
  83. quantum/core/features/ui_engine/src/__init__.py +20 -0
  84. quantum/core/features/ui_engine/src/ast_nodes.py +1854 -0
  85. quantum/core/features/ui_engine/src/parser.py +1106 -0
  86. quantum/core/features/websocket/src/__init__.py +24 -0
  87. quantum/core/features/websocket/src/ast_node.py +247 -0
  88. quantum/core/html_compat.py +299 -0
  89. quantum/core/parser.py +1235 -0
  90. quantum/core/parser_registry.py +213 -0
  91. quantum/core/parsers/__init__.py +76 -0
  92. quantum/core/parsers/ai/__init__.py +12 -0
  93. quantum/core/parsers/ai/agent_parser.py +106 -0
  94. quantum/core/parsers/ai/knowledge_parser.py +86 -0
  95. quantum/core/parsers/ai/llm_parser.py +78 -0
  96. quantum/core/parsers/ai/team_parser.py +88 -0
  97. quantum/core/parsers/base.py +322 -0
  98. quantum/core/parsers/composition/__init__.py +10 -0
  99. quantum/core/parsers/composition/import_parser.py +50 -0
  100. quantum/core/parsers/composition/slot_parser.py +48 -0
  101. quantum/core/parsers/control_flow/__init__.py +11 -0
  102. quantum/core/parsers/control_flow/if_parser.py +68 -0
  103. quantum/core/parsers/control_flow/loop_parser.py +105 -0
  104. quantum/core/parsers/control_flow/set_parser.py +89 -0
  105. quantum/core/parsers/data/__init__.py +12 -0
  106. quantum/core/parsers/data/data_parser.py +217 -0
  107. quantum/core/parsers/data/invoke_parser.py +116 -0
  108. quantum/core/parsers/data/query_parser.py +188 -0
  109. quantum/core/parsers/data/transaction_parser.py +77 -0
  110. quantum/core/parsers/events/__init__.py +9 -0
  111. quantum/core/parsers/events/dispatch_event_parser.py +44 -0
  112. quantum/core/parsers/forms/__init__.py +11 -0
  113. quantum/core/parsers/forms/action_parser.py +54 -0
  114. quantum/core/parsers/forms/flash_parser.py +34 -0
  115. quantum/core/parsers/forms/redirect_parser.py +33 -0
  116. quantum/core/parsers/functions/__init__.py +11 -0
  117. quantum/core/parsers/functions/function_parser.py +137 -0
  118. quantum/core/parsers/functions/param_parser.py +66 -0
  119. quantum/core/parsers/functions/return_parser.py +31 -0
  120. quantum/core/parsers/html/__init__.py +10 -0
  121. quantum/core/parsers/html/component_call_parser.py +130 -0
  122. quantum/core/parsers/html/html_parser.py +115 -0
  123. quantum/core/parsers/jobs/__init__.py +11 -0
  124. quantum/core/parsers/jobs/job_parser.py +71 -0
  125. quantum/core/parsers/jobs/schedule_parser.py +62 -0
  126. quantum/core/parsers/jobs/thread_parser.py +57 -0
  127. quantum/core/parsers/messaging/__init__.py +17 -0
  128. quantum/core/parsers/messaging/message_ack_parser.py +30 -0
  129. quantum/core/parsers/messaging/message_nack_parser.py +30 -0
  130. quantum/core/parsers/messaging/message_parser.py +114 -0
  131. quantum/core/parsers/messaging/queue_parser.py +61 -0
  132. quantum/core/parsers/messaging/websocket_parser.py +121 -0
  133. quantum/core/parsers/persistence/__init__.py +9 -0
  134. quantum/core/parsers/persistence/persist_parser.py +64 -0
  135. quantum/core/parsers/routing/__init__.py +9 -0
  136. quantum/core/parsers/routing/route_parser.py +41 -0
  137. quantum/core/parsers/scripting/__init__.py +12 -0
  138. quantum/core/parsers/scripting/pyclass_parser.py +62 -0
  139. quantum/core/parsers/scripting/pydecorator_parser.py +68 -0
  140. quantum/core/parsers/scripting/pyimport_parser.py +52 -0
  141. quantum/core/parsers/scripting/python_parser.py +49 -0
  142. quantum/core/parsers/services/__init__.py +12 -0
  143. quantum/core/parsers/services/dump_parser.py +52 -0
  144. quantum/core/parsers/services/file_parser.py +48 -0
  145. quantum/core/parsers/services/log_parser.py +46 -0
  146. quantum/core/parsers/services/mail_parser.py +65 -0
  147. quantum/core/tiers.py +82 -0
  148. quantum/packages/__init__.py +28 -0
  149. quantum/packages/manager.py +413 -0
  150. quantum/packages/manifest.py +351 -0
  151. quantum/packages/registry.py +399 -0
  152. quantum/packages/resolver.py +336 -0
  153. quantum/plugins/__init__.py +33 -0
  154. quantum/plugins/hooks.py +329 -0
  155. quantum/plugins/loader.py +479 -0
  156. quantum/plugins/manifest.py +336 -0
  157. quantum/plugins/registry.py +371 -0
  158. quantum/runtime/__init__.py +28 -0
  159. quantum/runtime/action_handler.py +443 -0
  160. quantum/runtime/adapters/__init__.py +88 -0
  161. quantum/runtime/adapters/memory_adapter.py +690 -0
  162. quantum/runtime/adapters/rabbitmq_adapter.py +715 -0
  163. quantum/runtime/adapters/redis_adapter.py +582 -0
  164. quantum/runtime/adapters/sqlite_adapter.py +414 -0
  165. quantum/runtime/agent_service.py +1133 -0
  166. quantum/runtime/api_server.py +86 -0
  167. quantum/runtime/ast_cache.py +506 -0
  168. quantum/runtime/auth_service.py +267 -0
  169. quantum/runtime/component.py +990 -0
  170. quantum/runtime/component_composer.py +319 -0
  171. quantum/runtime/component_resolver.py +174 -0
  172. quantum/runtime/database_service.py +598 -0
  173. quantum/runtime/email_service.py +162 -0
  174. quantum/runtime/error_handler.py +295 -0
  175. quantum/runtime/execution_context.py +286 -0
  176. quantum/runtime/executor_registry.py +171 -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 +262 -0
  184. quantum/runtime/executors/control_flow/__init__.py +11 -0
  185. quantum/runtime/executors/control_flow/if_executor.py +93 -0
  186. quantum/runtime/executors/control_flow/loop_executor.py +307 -0
  187. quantum/runtime/executors/control_flow/set_executor.py +412 -0
  188. quantum/runtime/executors/data/__init__.py +12 -0
  189. quantum/runtime/executors/data/data_executor.py +145 -0
  190. quantum/runtime/executors/data/invoke_executor.py +176 -0
  191. quantum/runtime/executors/data/query_executor.py +256 -0
  192. quantum/runtime/executors/data/transaction_executor.py +91 -0
  193. quantum/runtime/executors/jobs/__init__.py +11 -0
  194. quantum/runtime/executors/jobs/job_executor.py +190 -0
  195. quantum/runtime/executors/jobs/schedule_executor.py +132 -0
  196. quantum/runtime/executors/jobs/thread_executor.py +127 -0
  197. quantum/runtime/executors/messaging/__init__.py +17 -0
  198. quantum/runtime/executors/messaging/message_ack_executor.py +51 -0
  199. quantum/runtime/executors/messaging/message_executor.py +174 -0
  200. quantum/runtime/executors/messaging/queue_executor.py +103 -0
  201. quantum/runtime/executors/messaging/websocket_executor.py +197 -0
  202. quantum/runtime/executors/scripting/__init__.py +11 -0
  203. quantum/runtime/executors/scripting/pyclass_executor.py +90 -0
  204. quantum/runtime/executors/scripting/pyimport_executor.py +81 -0
  205. quantum/runtime/executors/scripting/python_executor.py +249 -0
  206. quantum/runtime/executors/services/__init__.py +12 -0
  207. quantum/runtime/executors/services/dump_executor.py +72 -0
  208. quantum/runtime/executors/services/file_executor.py +89 -0
  209. quantum/runtime/executors/services/log_executor.py +77 -0
  210. quantum/runtime/executors/services/mail_executor.py +81 -0
  211. quantum/runtime/expression_cache.py +498 -0
  212. quantum/runtime/file_upload_service.py +326 -0
  213. quantum/runtime/function_registry.py +118 -0
  214. quantum/runtime/game_builder.py +166 -0
  215. quantum/runtime/game_code_generator.py +2371 -0
  216. quantum/runtime/game_templates.py +2006 -0
  217. quantum/runtime/godot_code_generator.py +4681 -0
  218. quantum/runtime/godot_templates.py +1449 -0
  219. quantum/runtime/job_executor.py +1599 -0
  220. quantum/runtime/knowledge_service.py +500 -0
  221. quantum/runtime/llm_cache.py +100 -0
  222. quantum/runtime/llm_providers.py +704 -0
  223. quantum/runtime/llm_service.py +287 -0
  224. quantum/runtime/logging_setup.py +140 -0
  225. quantum/runtime/message_broker.py +364 -0
  226. quantum/runtime/message_queue_service.py +571 -0
  227. quantum/runtime/param_validation.py +184 -0
  228. quantum/runtime/pypy_compat.py +315 -0
  229. quantum/runtime/python_bridge.py +698 -0
  230. quantum/runtime/query_validators.py +304 -0
  231. quantum/runtime/renderer.py +733 -0
  232. quantum/runtime/service_container.py +444 -0
  233. quantum/runtime/terminal_builder.py +76 -0
  234. quantum/runtime/terminal_code_generator.py +607 -0
  235. quantum/runtime/terminal_templates.py +243 -0
  236. quantum/runtime/testing_builder.py +77 -0
  237. quantum/runtime/testing_code_generator.py +833 -0
  238. quantum/runtime/testing_templates.py +85 -0
  239. quantum/runtime/ui_builder.py +188 -0
  240. quantum/runtime/ui_desktop_adapter.py +1730 -0
  241. quantum/runtime/ui_desktop_templates.py +307 -0
  242. quantum/runtime/ui_html_adapter.py +2691 -0
  243. quantum/runtime/ui_html_templates.py +2297 -0
  244. quantum/runtime/ui_mobile_adapter.py +1832 -0
  245. quantum/runtime/ui_mobile_templates.py +1003 -0
  246. quantum/runtime/ui_textual_adapter.py +1866 -0
  247. quantum/runtime/ui_textual_templates.py +45 -0
  248. quantum/runtime/ui_tokens.py +465 -0
  249. quantum/runtime/ui_validator.py +365 -0
  250. quantum/runtime/validators.py +256 -0
  251. quantum/runtime/web_server.py +1766 -0
  252. quantum/runtime/websocket_adapter.py +501 -0
  253. quantum/runtime/websocket_service.py +585 -0
  254. quantum/runtime/websocket_transport.py +289 -0
  255. quantum/runtime/wsgi.py +101 -0
  256. quantum/utils/__init__.py +1 -0
  257. quantum_framework-0.9.0.dist-info/METADATA +244 -0
  258. quantum_framework-0.9.0.dist-info/RECORD +262 -0
  259. quantum_framework-0.9.0.dist-info/WHEEL +5 -0
  260. quantum_framework-0.9.0.dist-info/entry_points.txt +2 -0
  261. quantum_framework-0.9.0.dist-info/licenses/LICENSE +21 -0
  262. quantum_framework-0.9.0.dist-info/top_level.txt +1 -0
@@ -0,0 +1,560 @@
1
+ """
2
+ AST Nodes for Terminal Engine (qt: namespace)
3
+
4
+ All terminal-specific AST nodes for the Quantum Terminal UI engine.
5
+ These represent TUI widgets, layouts, and interactions
6
+ that compile to Python Textual applications.
7
+ """
8
+
9
+ from typing import Dict, Any, List, Optional
10
+ from dataclasses import dataclass, field
11
+ import sys
12
+ from pathlib import Path
13
+ from quantum.core.ast_nodes import QuantumNode
14
+
15
+
16
+ # ============================================
17
+ # CORE TERMINAL NODES
18
+ # ============================================
19
+
20
+ class ScreenNode(QuantumNode):
21
+ """Represents <qt:screen> - A full terminal screen (Textual Screen)."""
22
+
23
+ def __init__(self, name: str):
24
+ self.name = name
25
+ self.title: Optional[str] = None
26
+ self.children: List[QuantumNode] = []
27
+
28
+ def add_child(self, child: QuantumNode):
29
+ self.children.append(child)
30
+
31
+ def to_dict(self) -> Dict[str, Any]:
32
+ return {
33
+ "type": "terminal_screen",
34
+ "name": self.name,
35
+ "title": self.title,
36
+ "children_count": len(self.children),
37
+ }
38
+
39
+ def validate(self) -> List[str]:
40
+ errors = []
41
+ if not self.name:
42
+ errors.append("Screen name is required")
43
+ for child in self.children:
44
+ if hasattr(child, 'validate'):
45
+ errors.extend(child.validate())
46
+ return errors
47
+
48
+
49
+ class PanelNode(QuantumNode):
50
+ """Represents <qt:panel> - Container with border and title (Vertical + border CSS)."""
51
+
52
+ def __init__(self):
53
+ self.panel_id: Optional[str] = None
54
+ self.title: Optional[str] = None
55
+ self.children: List[QuantumNode] = []
56
+
57
+ def add_child(self, child: QuantumNode):
58
+ self.children.append(child)
59
+
60
+ def to_dict(self) -> Dict[str, Any]:
61
+ return {
62
+ "type": "terminal_panel",
63
+ "id": self.panel_id,
64
+ "title": self.title,
65
+ "children_count": len(self.children),
66
+ }
67
+
68
+ def validate(self) -> List[str]:
69
+ errors = []
70
+ for child in self.children:
71
+ if hasattr(child, 'validate'):
72
+ errors.extend(child.validate())
73
+ return errors
74
+
75
+
76
+ class LayoutNode(QuantumNode):
77
+ """Represents <qt:layout> - Horizontal/Vertical layout container."""
78
+
79
+ def __init__(self):
80
+ self.layout_id: Optional[str] = None
81
+ self.direction: str = "vertical" # horizontal, vertical
82
+ self.children: List[QuantumNode] = []
83
+
84
+ def add_child(self, child: QuantumNode):
85
+ self.children.append(child)
86
+
87
+ def to_dict(self) -> Dict[str, Any]:
88
+ return {
89
+ "type": "terminal_layout",
90
+ "id": self.layout_id,
91
+ "direction": self.direction,
92
+ "children_count": len(self.children),
93
+ }
94
+
95
+ def validate(self) -> List[str]:
96
+ errors = []
97
+ if self.direction not in ('horizontal', 'vertical'):
98
+ errors.append(f"Invalid layout direction: {self.direction}")
99
+ for child in self.children:
100
+ if hasattr(child, 'validate'):
101
+ errors.extend(child.validate())
102
+ return errors
103
+
104
+
105
+ class TableNode(QuantumNode):
106
+ """Represents <qt:table> - Data table (Textual DataTable)."""
107
+
108
+ def __init__(self):
109
+ self.table_id: Optional[str] = None
110
+ self.data_source: Optional[str] = None
111
+ self.zebra: bool = False
112
+ self.columns: List['ColumnNode'] = []
113
+
114
+ def add_column(self, col: 'ColumnNode'):
115
+ self.columns.append(col)
116
+
117
+ def to_dict(self) -> Dict[str, Any]:
118
+ return {
119
+ "type": "terminal_table",
120
+ "id": self.table_id,
121
+ "data_source": self.data_source,
122
+ "zebra": self.zebra,
123
+ "columns_count": len(self.columns),
124
+ }
125
+
126
+ def validate(self) -> List[str]:
127
+ errors = []
128
+ for col in self.columns:
129
+ errors.extend(col.validate())
130
+ return errors
131
+
132
+
133
+ class ColumnNode(QuantumNode):
134
+ """Represents <qt:column> - Table column definition."""
135
+
136
+ def __init__(self):
137
+ self.name: str = ""
138
+ self.key: str = ""
139
+ self.width: Optional[int] = None
140
+ self.align: str = "left" # left, center, right
141
+
142
+ def to_dict(self) -> Dict[str, Any]:
143
+ return {
144
+ "type": "terminal_column",
145
+ "name": self.name,
146
+ "key": self.key,
147
+ "width": self.width,
148
+ "align": self.align,
149
+ }
150
+
151
+ def validate(self) -> List[str]:
152
+ errors = []
153
+ if not self.name:
154
+ errors.append("Column name is required")
155
+ if not self.key:
156
+ errors.append("Column key is required")
157
+ return errors
158
+
159
+
160
+ class TerminalInputNode(QuantumNode):
161
+ """Represents <qt:input> - Text input field (Textual Input)."""
162
+
163
+ def __init__(self):
164
+ self.input_id: Optional[str] = None
165
+ self.placeholder: Optional[str] = None
166
+ self.on_submit: Optional[str] = None
167
+ self.password: bool = False
168
+
169
+ def to_dict(self) -> Dict[str, Any]:
170
+ return {
171
+ "type": "terminal_input",
172
+ "id": self.input_id,
173
+ "placeholder": self.placeholder,
174
+ "on_submit": self.on_submit,
175
+ }
176
+
177
+ def validate(self) -> List[str]:
178
+ return []
179
+
180
+
181
+ class ButtonNode(QuantumNode):
182
+ """Represents <qt:button> - Clickable button (Textual Button)."""
183
+
184
+ def __init__(self):
185
+ self.button_id: Optional[str] = None
186
+ self.label: str = ""
187
+ self.variant: str = "default" # default, primary, success, warning, error
188
+ self.on_click: Optional[str] = None
189
+
190
+ def to_dict(self) -> Dict[str, Any]:
191
+ return {
192
+ "type": "terminal_button",
193
+ "id": self.button_id,
194
+ "label": self.label,
195
+ "variant": self.variant,
196
+ "on_click": self.on_click,
197
+ }
198
+
199
+ def validate(self) -> List[str]:
200
+ errors = []
201
+ if not self.label:
202
+ errors.append("Button label is required")
203
+ return errors
204
+
205
+
206
+ class MenuNode(QuantumNode):
207
+ """Represents <qt:menu> - Selection menu (Textual OptionList)."""
208
+
209
+ def __init__(self):
210
+ self.menu_id: Optional[str] = None
211
+ self.on_select: Optional[str] = None
212
+ self.options: List['OptionNode'] = []
213
+
214
+ def add_option(self, opt: 'OptionNode'):
215
+ self.options.append(opt)
216
+
217
+ def to_dict(self) -> Dict[str, Any]:
218
+ return {
219
+ "type": "terminal_menu",
220
+ "id": self.menu_id,
221
+ "on_select": self.on_select,
222
+ "options_count": len(self.options),
223
+ }
224
+
225
+ def validate(self) -> List[str]:
226
+ return []
227
+
228
+
229
+ class OptionNode(QuantumNode):
230
+ """Represents <qt:option> - Menu option item."""
231
+
232
+ def __init__(self):
233
+ self.value: str = ""
234
+ self.label: str = ""
235
+
236
+ def to_dict(self) -> Dict[str, Any]:
237
+ return {
238
+ "type": "terminal_option",
239
+ "value": self.value,
240
+ "label": self.label,
241
+ }
242
+
243
+ def validate(self) -> List[str]:
244
+ errors = []
245
+ if not self.label:
246
+ errors.append("Option label is required")
247
+ return errors
248
+
249
+
250
+ class TextNode_Terminal(QuantumNode):
251
+ """Represents <qt:text> - Styled text display (Textual Static with Rich markup)."""
252
+
253
+ def __init__(self):
254
+ self.text_id: Optional[str] = None
255
+ self.content: str = ""
256
+
257
+ def to_dict(self) -> Dict[str, Any]:
258
+ return {
259
+ "type": "terminal_text",
260
+ "id": self.text_id,
261
+ "content": self.content,
262
+ }
263
+
264
+ def validate(self) -> List[str]:
265
+ return []
266
+
267
+
268
+ class ProgressNode(QuantumNode):
269
+ """Represents <qt:progress> - Progress bar (Textual ProgressBar)."""
270
+
271
+ def __init__(self):
272
+ self.progress_id: Optional[str] = None
273
+ self.total: float = 100
274
+ self.value_var: Optional[str] = None
275
+
276
+ def to_dict(self) -> Dict[str, Any]:
277
+ return {
278
+ "type": "terminal_progress",
279
+ "id": self.progress_id,
280
+ "total": self.total,
281
+ "value_var": self.value_var,
282
+ }
283
+
284
+ def validate(self) -> List[str]:
285
+ return []
286
+
287
+
288
+ class TreeNode(QuantumNode):
289
+ """Represents <qt:tree> - Tree view (Textual Tree/DirectoryTree)."""
290
+
291
+ def __init__(self):
292
+ self.tree_id: Optional[str] = None
293
+ self.label: str = ""
294
+ self.on_select: Optional[str] = None
295
+
296
+ def to_dict(self) -> Dict[str, Any]:
297
+ return {
298
+ "type": "terminal_tree",
299
+ "id": self.tree_id,
300
+ "label": self.label,
301
+ "on_select": self.on_select,
302
+ }
303
+
304
+ def validate(self) -> List[str]:
305
+ return []
306
+
307
+
308
+ class TabsNode(QuantumNode):
309
+ """Represents <qt:tabs> - Tabbed content container (Textual TabbedContent)."""
310
+
311
+ def __init__(self):
312
+ self.tabs_id: Optional[str] = None
313
+ self.tabs: List['TabNode'] = []
314
+
315
+ def add_tab(self, tab: 'TabNode'):
316
+ self.tabs.append(tab)
317
+
318
+ def to_dict(self) -> Dict[str, Any]:
319
+ return {
320
+ "type": "terminal_tabs",
321
+ "id": self.tabs_id,
322
+ "tabs_count": len(self.tabs),
323
+ }
324
+
325
+ def validate(self) -> List[str]:
326
+ errors = []
327
+ for tab in self.tabs:
328
+ errors.extend(tab.validate())
329
+ return errors
330
+
331
+
332
+ class TabNode(QuantumNode):
333
+ """Represents <qt:tab> - Individual tab pane (Textual TabPane)."""
334
+
335
+ def __init__(self):
336
+ self.tab_id: Optional[str] = None
337
+ self.title: str = ""
338
+ self.children: List[QuantumNode] = []
339
+
340
+ def add_child(self, child: QuantumNode):
341
+ self.children.append(child)
342
+
343
+ def to_dict(self) -> Dict[str, Any]:
344
+ return {
345
+ "type": "terminal_tab",
346
+ "id": self.tab_id,
347
+ "title": self.title,
348
+ "children_count": len(self.children),
349
+ }
350
+
351
+ def validate(self) -> List[str]:
352
+ errors = []
353
+ if not self.title:
354
+ errors.append("Tab title is required")
355
+ for child in self.children:
356
+ if hasattr(child, 'validate'):
357
+ errors.extend(child.validate())
358
+ return errors
359
+
360
+
361
+ class LogNode_Terminal(QuantumNode):
362
+ """Represents <qt:log> - Scrollable log output (Textual RichLog)."""
363
+
364
+ def __init__(self):
365
+ self.log_id: Optional[str] = None
366
+ self.auto_scroll: bool = True
367
+ self.markup: bool = True
368
+ self.max_lines: Optional[int] = None
369
+
370
+ def to_dict(self) -> Dict[str, Any]:
371
+ return {
372
+ "type": "terminal_log",
373
+ "id": self.log_id,
374
+ "auto_scroll": self.auto_scroll,
375
+ "markup": self.markup,
376
+ "max_lines": self.max_lines,
377
+ }
378
+
379
+ def validate(self) -> List[str]:
380
+ return []
381
+
382
+
383
+ class HeaderNode_Terminal(QuantumNode):
384
+ """Represents <qt:header> - Fixed header bar (Textual Header)."""
385
+
386
+ def __init__(self):
387
+ self.title: Optional[str] = None
388
+ self.show_clock: bool = False
389
+
390
+ def to_dict(self) -> Dict[str, Any]:
391
+ return {
392
+ "type": "terminal_header",
393
+ "title": self.title,
394
+ "show_clock": self.show_clock,
395
+ }
396
+
397
+ def validate(self) -> List[str]:
398
+ return []
399
+
400
+
401
+ class FooterNode(QuantumNode):
402
+ """Represents <qt:footer> - Fixed footer bar (Textual Footer)."""
403
+
404
+ def __init__(self):
405
+ pass
406
+
407
+ def to_dict(self) -> Dict[str, Any]:
408
+ return {
409
+ "type": "terminal_footer",
410
+ }
411
+
412
+ def validate(self) -> List[str]:
413
+ return []
414
+
415
+
416
+ class StatusNode(QuantumNode):
417
+ """Represents <qt:status> - Status bar (Textual Static)."""
418
+
419
+ def __init__(self):
420
+ self.status_id: Optional[str] = None
421
+ self.content: str = ""
422
+
423
+ def to_dict(self) -> Dict[str, Any]:
424
+ return {
425
+ "type": "terminal_status",
426
+ "id": self.status_id,
427
+ "content": self.content,
428
+ }
429
+
430
+ def validate(self) -> List[str]:
431
+ return []
432
+
433
+
434
+ class KeybindingNode(QuantumNode):
435
+ """Represents <qt:keybinding> - Keyboard shortcut (Textual Binding)."""
436
+
437
+ def __init__(self):
438
+ self.key: str = ""
439
+ self.action: str = ""
440
+ self.description: Optional[str] = None
441
+
442
+ def to_dict(self) -> Dict[str, Any]:
443
+ return {
444
+ "type": "terminal_keybinding",
445
+ "key": self.key,
446
+ "action": self.action,
447
+ "description": self.description,
448
+ }
449
+
450
+ def validate(self) -> List[str]:
451
+ errors = []
452
+ if not self.key:
453
+ errors.append("Keybinding key is required")
454
+ if not self.action:
455
+ errors.append("Keybinding action is required")
456
+ return errors
457
+
458
+
459
+ class TimerNode_Terminal(QuantumNode):
460
+ """Represents <qt:timer> - Periodic timer (set_interval)."""
461
+
462
+ def __init__(self):
463
+ self.timer_id: Optional[str] = None
464
+ self.interval: float = 1.0
465
+ self.action: str = ""
466
+
467
+ def to_dict(self) -> Dict[str, Any]:
468
+ return {
469
+ "type": "terminal_timer",
470
+ "id": self.timer_id,
471
+ "interval": self.interval,
472
+ "action": self.action,
473
+ }
474
+
475
+ def validate(self) -> List[str]:
476
+ errors = []
477
+ if not self.action:
478
+ errors.append("Timer action is required")
479
+ if self.interval <= 0:
480
+ errors.append("Timer interval must be positive")
481
+ return errors
482
+
483
+
484
+ class ServiceNode(QuantumNode):
485
+ """Represents <qt:service> - Background async worker."""
486
+
487
+ def __init__(self):
488
+ self.service_id: Optional[str] = None
489
+ self.handler: str = ""
490
+
491
+ def to_dict(self) -> Dict[str, Any]:
492
+ return {
493
+ "type": "terminal_service",
494
+ "id": self.service_id,
495
+ "handler": self.handler,
496
+ }
497
+
498
+ def validate(self) -> List[str]:
499
+ errors = []
500
+ if not self.handler:
501
+ errors.append("Service handler is required")
502
+ return errors
503
+
504
+
505
+ class CssNode(QuantumNode):
506
+ """Represents <qt:css> - Textual CSS (TCSS) block."""
507
+
508
+ def __init__(self):
509
+ self.content: str = ""
510
+
511
+ def to_dict(self) -> Dict[str, Any]:
512
+ return {
513
+ "type": "terminal_css",
514
+ "content_length": len(self.content),
515
+ }
516
+
517
+ def validate(self) -> List[str]:
518
+ return []
519
+
520
+
521
+ class OnEventNode_Terminal(QuantumNode):
522
+ """Represents <qt:on> - Event handler mapping."""
523
+
524
+ def __init__(self):
525
+ self.event: str = ""
526
+ self.action: str = ""
527
+
528
+ def to_dict(self) -> Dict[str, Any]:
529
+ return {
530
+ "type": "terminal_on_event",
531
+ "event": self.event,
532
+ "action": self.action,
533
+ }
534
+
535
+ def validate(self) -> List[str]:
536
+ errors = []
537
+ if not self.event:
538
+ errors.append("Event type is required")
539
+ if not self.action:
540
+ errors.append("Event action is required")
541
+ return errors
542
+
543
+
544
+ class RawCodeNode_Terminal(QuantumNode):
545
+ """Represents raw Python code inside a q:function in terminal context."""
546
+
547
+ def __init__(self, code: str):
548
+ self.code = code
549
+
550
+ def to_dict(self) -> Dict[str, Any]:
551
+ return {
552
+ "type": "raw_code",
553
+ "code": self.code,
554
+ }
555
+
556
+ def validate(self) -> List[str]:
557
+ errors = []
558
+ if not self.code or not self.code.strip():
559
+ errors.append("RawCodeNode code is empty")
560
+ return errors