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,65 @@
1
+ <q:component name="AdminLogin">
2
+ <!--
3
+ Login do admin. Usa as mesmas credenciais do FastAPI (admin.auth.login:
4
+ ADMIN_PASSWORD, ou a senha gerada e impressa na subida), com bloqueio
5
+ depois de tentativas erradas seguidas. Grava na sessão o que AUTH-1 exige.
6
+ -->
7
+ <q:action name="signIn" method="POST">
8
+ <q:param name="username" type="string" required="true" />
9
+ <q:param name="password" type="string" required="true" />
10
+
11
+ <q:invoke name="auth" service="admin.auth.login">
12
+ <q:param name="username" value="{username}" />
13
+ <q:param name="password" value="{password}" />
14
+ </q:invoke>
15
+
16
+ <q:if condition="auth.ok">
17
+ <q:set name="session.authenticated" value="true" type="boolean" />
18
+ <q:set name="session.userName" value="{auth.username}" />
19
+ <q:set name="session.userRole" value="{auth.role}" />
20
+ <q:set name="session.sessionExpiry" value="{dateAdd('h', auth.expires_in_hours)}" />
21
+ <q:redirect url="/admin/applications" />
22
+ </q:if>
23
+
24
+ <q:flash type="error" message="{auth.error}" />
25
+ <q:redirect url="/admin/login" />
26
+ </q:action>
27
+
28
+ <html lang="en">
29
+ <head>
30
+ <meta charset="UTF-8" />
31
+ <meta name="viewport" content="width=device-width, initial-scale=1.0" />
32
+ <title>Sign in - Quantum Admin</title>
33
+ <link rel="stylesheet" href="/static/quantum-admin.css" />
34
+ </head>
35
+ <body>
36
+ <main class="qa-login">
37
+ <div class="qa-card qa-login-card">
38
+ <div class="qa-card-header">
39
+ <div class="qa-sidebar-logo-icon">Q</div>
40
+ <div class="qa-card-title">Quantum Admin</div>
41
+ </div>
42
+ <div class="qa-card-body">
43
+ <q:if condition="flash">
44
+ <div class="{'qa-flash qa-flash-error' if flashType == 'error' else 'qa-flash qa-flash-success'}" role="alert">{flash}</div>
45
+ </q:if>
46
+ <q:if condition="query.expired">
47
+ <div class="qa-flash qa-flash-error" role="alert">Your session expired. Sign in again.</div>
48
+ </q:if>
49
+ <form method="POST" action="/admin/login">
50
+ <div class="qa-form-group qa-mb-4">
51
+ <label class="qa-label" for="username">User</label>
52
+ <input id="username" type="text" name="username" class="qa-input" autocomplete="username" required="" autofocus="" />
53
+ </div>
54
+ <div class="qa-form-group qa-mb-4">
55
+ <label class="qa-label" for="password">Password</label>
56
+ <input id="password" type="password" name="password" class="qa-input" autocomplete="current-password" required="" />
57
+ </div>
58
+ <button type="submit" class="qa-btn qa-btn-primary">Sign in</button>
59
+ </form>
60
+ </div>
61
+ </div>
62
+ </main>
63
+ </body>
64
+ </html>
65
+ </q:component>
@@ -0,0 +1,11 @@
1
+ <q:component name="AdminLogout">
2
+ <!-- Sair: só por POST (o botão da barra lateral), para um link não derrubar a sessão. -->
3
+ <q:action name="signOut" method="POST">
4
+ <q:set name="session.authenticated" value="false" type="boolean" />
5
+ <q:set name="session.userName" value="" />
6
+ <q:set name="session.userRole" value="" />
7
+ <q:redirect url="/admin/login" flash="Signed out" />
8
+ </q:action>
9
+
10
+ <html lang="en"><body><p>Use the Sign out button.</p></body></html>
11
+ </q:component>
@@ -0,0 +1,174 @@
1
+ <q:component name="AdminSettings" require_auth="true" require_role="admin" login_url="/admin/login">
2
+ <!--
3
+ quantum.config.yaml da raiz (admin.settings.*) e o ambiente
4
+ (admin.system.info). Salvar muda só as linhas dos valores e mantém os
5
+ comentários; a versão anterior regravava o arquivo inteiro com yaml.dump.
6
+ O formulário vem preenchido com o que está no arquivo — antes vinha com
7
+ debug desligado, log INFO e TTL 300, e salvar trocava esses valores sem
8
+ ninguém ter mexido neles.
9
+ -->
10
+ <q:import component="AdminShell" from="admin/_layout" />
11
+
12
+ <q:action name="saveSettings" method="POST">
13
+ <q:param name="port" type="integer" required="true" />
14
+ <q:param name="host" type="string" required="true" />
15
+ <q:param name="debug" type="boolean" default="false" />
16
+ <q:param name="reload" type="boolean" default="false" />
17
+ <q:param name="cache_templates" type="boolean" default="false" />
18
+ <q:param name="cache_ttl" type="integer" default="0" />
19
+ <q:param name="log_level" type="string" required="true" />
20
+ <q:param name="xss_protection" type="boolean" default="false" />
21
+ <q:param name="cors_enabled" type="boolean" default="false" />
22
+ <q:invoke name="salvo" service="admin.settings.save_server_config" onerror="continue">
23
+ <q:param name="port" value="{port}" type="integer" />
24
+ <q:param name="host" value="{host}" />
25
+ <q:param name="debug" value="{debug}" type="boolean" />
26
+ <q:param name="reload" value="{reload}" type="boolean" />
27
+ <q:param name="cache_templates" value="{cache_templates}" type="boolean" />
28
+ <q:param name="cache_ttl" value="{cache_ttl}" type="integer" />
29
+ <q:param name="log_level" value="{log_level}" />
30
+ <q:param name="xss_protection" value="{xss_protection}" type="boolean" />
31
+ <q:param name="cors_enabled" value="{cors_enabled}" type="boolean" />
32
+ </q:invoke>
33
+ <q:if condition="salvo_result.success">
34
+ <q:redirect url="/admin/settings" flash="Saved. The server reads quantum.config.yaml when it starts: restart it to apply." />
35
+ </q:if>
36
+ <q:flash type="error" message="{salvo_result.error.message}" />
37
+ <q:redirect url="/admin/settings" />
38
+ </q:action>
39
+
40
+ <q:invoke name="cfg" service="admin.settings.server_config" />
41
+ <q:invoke name="sistema" service="admin.system.info" />
42
+
43
+ <AdminShell title="Settings" active="settings" flash="{flash}" flashType="{flashType}">
44
+
45
+ <q:if condition="not cfg.found">
46
+ <div class="qa-flash qa-flash-error" role="alert">There is no quantum.config.yaml in {sistema.root}.</div>
47
+ </q:if>
48
+ <q:if condition="cfg.error">
49
+ <div class="qa-flash qa-flash-error" role="alert">quantum.config.yaml is not valid YAML: {cfg.error}</div>
50
+ </q:if>
51
+
52
+ <q:if condition="cfg.server">
53
+ <div class="qa-grid qa-grid-2 qa-mb-6">
54
+ <div class="qa-card">
55
+ <div class="qa-card-header"><div class="qa-card-title">Paths</div></div>
56
+ <div class="qa-card-body">
57
+ <div class="qa-flex qa-items-center qa-justify-between"><span class="qa-text-sm qa-text-muted">Components</span><span class="qa-font-mono">{cfg.paths.components}</span></div>
58
+ <div class="qa-flex qa-items-center qa-justify-between"><span class="qa-text-sm qa-text-muted">Static</span><span class="qa-font-mono">{cfg.paths.static}</span></div>
59
+ <div class="qa-flex qa-items-center qa-justify-between"><span class="qa-text-sm qa-text-muted">Logs</span><span class="qa-font-mono">{cfg.paths.logs}</span></div>
60
+ </div>
61
+ </div>
62
+
63
+ <div class="qa-card">
64
+ <div class="qa-card-header"><div class="qa-card-title">Declared</div></div>
65
+ <div class="qa-card-body">
66
+ <div class="qa-flex qa-items-center qa-justify-between"><span class="qa-text-sm qa-text-muted">Datasources</span><span class="qa-font-mono">{join(cfg.datasources, ', ') if cfg.datasources else '-'}</span></div>
67
+ <div class="qa-flex qa-items-center qa-justify-between"><span class="qa-text-sm qa-text-muted">Service modules</span><span class="qa-font-mono">{len(cfg.services)}</span></div>
68
+ <div class="qa-flex qa-items-center qa-justify-between"><span class="qa-text-sm qa-text-muted">LLM base URL</span><span class="qa-font-mono">{cfg.llm.base_url if 'base_url' in cfg.llm else '-'}</span></div>
69
+ </div>
70
+ </div>
71
+ </div>
72
+
73
+ <div class="qa-card qa-mb-6">
74
+ <div class="qa-card-header">
75
+ <div>
76
+ <div class="qa-card-title">Server Configuration</div>
77
+ <div class="qa-card-subtitle qa-font-mono">{cfg.path}</div>
78
+ </div>
79
+ </div>
80
+ <div class="qa-card-body">
81
+ <form method="POST" action="/admin/settings">
82
+ <input type="hidden" name="action" value="saveSettings" />
83
+ <div class="qa-grid qa-grid-2" style="gap: 24px;">
84
+ <div>
85
+ <div class="qa-form-group qa-mb-4">
86
+ <label class="qa-label" for="port">Port</label>
87
+ <input id="port" type="number" name="port" class="qa-input" value="{cfg.server.port}" min="1" max="65535" required="" />
88
+ </div>
89
+ <div class="qa-form-group qa-mb-4">
90
+ <label class="qa-label" for="host">Host</label>
91
+ <input id="host" type="text" name="host" class="qa-input" value="{cfg.server.host}" required="" />
92
+ <div class="qa-text-xs qa-text-muted">127.0.0.1 keeps the server reachable only from this machine.</div>
93
+ </div>
94
+ <div class="qa-flex qa-items-center qa-mb-4" style="gap: 8px;">
95
+ <q:if condition="cfg.server.debug">
96
+ <input type="checkbox" name="debug" id="debug" value="true" checked="checked" />
97
+ <q:else><input type="checkbox" name="debug" id="debug" value="true" /></q:else>
98
+ </q:if>
99
+ <label for="debug" class="qa-text-sm">Debug mode (only with a loopback host)</label>
100
+ </div>
101
+ <div class="qa-flex qa-items-center qa-mb-4" style="gap: 8px;">
102
+ <q:if condition="cfg.server.reload">
103
+ <input type="checkbox" name="reload" id="reload" value="true" checked="checked" />
104
+ <q:else><input type="checkbox" name="reload" id="reload" value="true" /></q:else>
105
+ </q:if>
106
+ <label for="reload" class="qa-text-sm">Auto-reload</label>
107
+ </div>
108
+ </div>
109
+
110
+ <div>
111
+ <div class="qa-form-group qa-mb-4">
112
+ <label class="qa-label" for="log_level">Log level</label>
113
+ <select id="log_level" name="log_level" class="qa-input">
114
+ <q:loop type="array" var="nivel" items="{['DEBUG', 'INFO', 'WARNING', 'ERROR', 'CRITICAL']}">
115
+ <q:if condition="upper(cfg.logging.level) == nivel">
116
+ <option value="{nivel}" selected="selected">{nivel}</option>
117
+ <q:else><option value="{nivel}">{nivel}</option></q:else>
118
+ </q:if>
119
+ </q:loop>
120
+ </select>
121
+ </div>
122
+ <div class="qa-form-group qa-mb-4">
123
+ <label class="qa-label" for="cache_ttl">Template cache TTL (seconds)</label>
124
+ <input id="cache_ttl" type="number" name="cache_ttl" class="qa-input" value="{cfg.performance.cache_ttl}" min="0" />
125
+ </div>
126
+ <div class="qa-flex qa-items-center qa-mb-4" style="gap: 8px;">
127
+ <q:if condition="cfg.performance.cache_templates">
128
+ <input type="checkbox" name="cache_templates" id="cache_templates" value="true" checked="checked" />
129
+ <q:else><input type="checkbox" name="cache_templates" id="cache_templates" value="true" /></q:else>
130
+ </q:if>
131
+ <label for="cache_templates" class="qa-text-sm">Template cache</label>
132
+ </div>
133
+ <div class="qa-flex qa-items-center qa-mb-4" style="gap: 8px;">
134
+ <q:if condition="cfg.security.xss_protection">
135
+ <input type="checkbox" name="xss_protection" id="xss_protection" value="true" checked="checked" />
136
+ <q:else><input type="checkbox" name="xss_protection" id="xss_protection" value="true" /></q:else>
137
+ </q:if>
138
+ <label for="xss_protection" class="qa-text-sm">XSS protection</label>
139
+ </div>
140
+ <div class="qa-flex qa-items-center qa-mb-4" style="gap: 8px;">
141
+ <q:if condition="cfg.security.cors_enabled">
142
+ <input type="checkbox" name="cors_enabled" id="cors_enabled" value="true" checked="checked" />
143
+ <q:else><input type="checkbox" name="cors_enabled" id="cors_enabled" value="true" /></q:else>
144
+ </q:if>
145
+ <label for="cors_enabled" class="qa-text-sm">CORS</label>
146
+ </div>
147
+ </div>
148
+ </div>
149
+ <button type="submit" class="qa-btn qa-btn-primary">Save Settings</button>
150
+ </form>
151
+ </div>
152
+ </div>
153
+ </q:if>
154
+
155
+ <div class="qa-card">
156
+ <div class="qa-card-header"><div class="qa-card-title">Runtime</div></div>
157
+ <div class="qa-card-body">
158
+ <div class="qa-grid qa-grid-2">
159
+ <div>
160
+ <div class="qa-flex qa-items-center qa-justify-between"><span class="qa-text-sm qa-text-muted">Quantum</span><span class="qa-font-mono">{sistema.quantum_version or 'not installed (running from a clone)'}</span></div>
161
+ <div class="qa-flex qa-items-center qa-justify-between"><span class="qa-text-sm qa-text-muted">Python</span><span class="qa-font-mono">{sistema.python_version}</span></div>
162
+ <div class="qa-flex qa-items-center qa-justify-between"><span class="qa-text-sm qa-text-muted">Platform</span><span class="qa-font-mono">{sistema.platform}</span></div>
163
+ </div>
164
+ <div>
165
+ <div class="qa-flex qa-items-center qa-justify-between"><span class="qa-text-sm qa-text-muted">Project root</span><span class="qa-font-mono">{sistema.root}</span></div>
166
+ <div class="qa-flex qa-items-center qa-justify-between"><span class="qa-text-sm qa-text-muted">Tags with a parser</span><span class="qa-font-mono">{sistema.parser_tags}</span></div>
167
+ <div class="qa-flex qa-items-center qa-justify-between"><span class="qa-text-sm qa-text-muted">Executors</span><span class="qa-font-mono">{sistema.executors}</span></div>
168
+ </div>
169
+ </div>
170
+ </div>
171
+ </div>
172
+
173
+ </AdminShell>
174
+ </q:component>
@@ -0,0 +1,45 @@
1
+ <q:component name="AdminSource" require_auth="true" require_role="admin" login_url="/admin/login">
2
+ <!--
3
+ Leitor de código (admin.source.read). O serviço recusa caminhos fora da
4
+ raiz e arquivos que podem ter credenciais (.env, chaves, bancos, os YAML
5
+ de settings) — a versão anterior mostrava todos eles.
6
+ -->
7
+ <q:import component="AdminShell" from="admin/_layout" />
8
+
9
+ <q:set name="arquivo" value="{query.file}" />
10
+ <q:invoke name="fonte" service="admin.source.read" onerror="continue">
11
+ <q:param name="path" value="{arquivo}" />
12
+ </q:invoke>
13
+
14
+ <AdminShell title="Source" active="" flash="{flash}" flashType="{flashType}">
15
+
16
+ <q:if condition="fonte_result.success">
17
+ <div class="qa-flex qa-items-center qa-mb-4" style="gap: 24px; flex-wrap: wrap;">
18
+ <span class="qa-font-mono qa-font-medium">{fonte.path}</span>
19
+ <span class="qa-badge qa-badge-info">{fonte.type}</span>
20
+ <span class="qa-text-sm qa-text-muted">{fonte.lines} lines</span>
21
+ <span class="qa-text-sm qa-text-muted">{fonte.size}</span>
22
+ <span class="qa-text-sm qa-text-muted">modified {fonte.modified}</span>
23
+ </div>
24
+ <div class="qa-card">
25
+ <div class="qa-card-body qa-p-0">
26
+ <div class="qa-source-viewer">
27
+ <div class="qa-source-gutter" id="sourceGutter"></div>
28
+ <pre class="qa-source-code" id="sourceCode">{fonte.content}</pre>
29
+ </div>
30
+ </div>
31
+ </div>
32
+ <script src="/static/quantum-source-highlight.js"></script>
33
+ </q:if>
34
+
35
+ <q:if condition="not fonte_result.success">
36
+ <div class="qa-card">
37
+ <div class="qa-empty">
38
+ <div class="qa-empty-title">Cannot Display Source</div>
39
+ <div class="qa-empty-text">{fonte_result.error.message}</div>
40
+ </div>
41
+ </div>
42
+ </q:if>
43
+
44
+ </AdminShell>
45
+ </q:component>
@@ -0,0 +1,73 @@
1
+ <q:component name="AdminTests" require_auth="true" require_role="admin" login_url="/admin/login">
2
+ <!-- Os test_*.py de tests/ (admin.tests.list). Rodar fica no detalhe do componente. -->
3
+ <q:import component="AdminShell" from="admin/_layout" />
4
+
5
+ <q:invoke name="suite" service="admin.tests.list" />
6
+
7
+ <AdminShell title="Tests" active="tests" flash="{flash}" flashType="{flashType}">
8
+
9
+ <div class="qa-grid qa-grid-3 qa-mb-6">
10
+ <div class="qa-stat-card">
11
+ <div class="qa-stat-label">Test Files</div>
12
+ <div class="qa-stat-value">{len(suite.files)}</div>
13
+ <div class="qa-stat-change"><span class="qa-text-muted">test_*.py files</span></div>
14
+ </div>
15
+ <div class="qa-stat-card">
16
+ <div class="qa-stat-label">Test Functions</div>
17
+ <div class="qa-stat-value">{suite.total_functions}</div>
18
+ <div class="qa-stat-change"><span class="qa-text-muted">def test_ definitions</span></div>
19
+ </div>
20
+ <div class="qa-stat-card">
21
+ <div class="qa-stat-label">Directories</div>
22
+ <div class="qa-stat-value">{len(suite.directories)}</div>
23
+ <div class="qa-stat-change"><span class="qa-text-muted">test groups</span></div>
24
+ </div>
25
+ </div>
26
+
27
+ <q:if condition="len(suite.directories) &gt; 0">
28
+ <div class="qa-card qa-mb-6">
29
+ <div class="qa-card-header">
30
+ <div class="qa-card-title">By Directory</div>
31
+ </div>
32
+ <div class="qa-card-body">
33
+ <div class="qa-grid qa-grid-3">
34
+ <q:loop type="array" var="pasta" items="{suite.directories}">
35
+ <div class="qa-stat-card">
36
+ <div class="qa-stat-label qa-font-mono">{pasta.name}</div>
37
+ <div class="qa-text-sm"><strong>{pasta.files}</strong> files · <strong>{pasta.functions}</strong> tests</div>
38
+ </div>
39
+ </q:loop>
40
+ </div>
41
+ </div>
42
+ </div>
43
+
44
+ <div class="qa-card">
45
+ <div class="qa-card-body qa-p-0" style="overflow-x: auto;">
46
+ <table class="qa-table">
47
+ <thead><tr><th>File</th><th>Functions</th><th>Directory</th><th></th></tr></thead>
48
+ <tbody>
49
+ <q:loop type="array" var="arquivo" items="{suite.files}">
50
+ <tr>
51
+ <td><span class="qa-font-mono">{arquivo.path}</span></td>
52
+ <td style="font-variant-numeric: tabular-nums;">{arquivo.functions}</td>
53
+ <td><span class="qa-badge qa-badge-info">{arquivo.directory}</span></td>
54
+ <td><a href="/admin/source?file=tests/{arquivo.path}" class="qa-text-sm">Source</a></td>
55
+ </tr>
56
+ </q:loop>
57
+ </tbody>
58
+ </table>
59
+ </div>
60
+ </div>
61
+ </q:if>
62
+
63
+ <q:if condition="len(suite.files) == 0">
64
+ <div class="qa-card">
65
+ <div class="qa-empty">
66
+ <div class="qa-empty-title">No Tests</div>
67
+ <div class="qa-empty-text">There is no test_*.py under tests/ in the project root. A component's page can generate one.</div>
68
+ </div>
69
+ </div>
70
+ </q:if>
71
+
72
+ </AdminShell>
73
+ </q:component>
quantum_admin/run.py ADDED
@@ -0,0 +1,13 @@
1
+ """
2
+ Run Quantum Admin API server
3
+ """
4
+ import uvicorn
5
+
6
+ if __name__ == "__main__":
7
+ uvicorn.run(
8
+ "backend.main:app",
9
+ host="0.0.0.0",
10
+ port=8000,
11
+ reload=True,
12
+ log_level="info"
13
+ )
@@ -0,0 +1,16 @@
1
+ """
2
+ Serviços declarados do Quantum Admin (passo A2 do plano de oficialização).
3
+
4
+ As telas .q de components/admin chamam estas funções com
5
+ `<q:invoke service="admin.<área>.<ação>">`. Elas envolvem a biblioteca que já
6
+ existia em quantum_admin/backend (modelos, crud, serviços), para que o admin
7
+ tenha UMA fonte de dados — o banco do admin — em vez de dois caminhos: o
8
+ FastAPI gravava no banco, e as telas .q em quantum_admin/settings/*.yaml.
9
+
10
+ Cada módulo registra os serviços de uma área:
11
+
12
+ admin.projects.* projects.py
13
+ admin.import.* yaml_import.py (traz os YAML antigos para o banco)
14
+
15
+ quantum.config.yaml lista os módulos em `services:` (SVC-2).
16
+ """
@@ -0,0 +1,84 @@
1
+ """Infraestrutura comum dos serviços do admin: sessão do banco, raiz, processos."""
2
+
3
+ import contextlib
4
+ import os
5
+ from pathlib import Path
6
+
7
+ _iniciado = False
8
+
9
+
10
+ def _database():
11
+ from quantum_admin.backend import database
12
+ return database
13
+
14
+
15
+ @contextlib.contextmanager
16
+ def sessao():
17
+ """Sessão do banco do admin (o mesmo do FastAPI), com as tabelas criadas.
18
+
19
+ commit no fim do bloco, rollback se ele levantar.
20
+ """
21
+ global _iniciado
22
+ database = _database()
23
+ if not _iniciado:
24
+ database.Base.metadata.create_all(bind=database.engine)
25
+ _iniciado = True
26
+ db = database.SessionLocal()
27
+ try:
28
+ yield db
29
+ db.commit()
30
+ except Exception:
31
+ db.rollback()
32
+ raise
33
+ finally:
34
+ db.close()
35
+
36
+
37
+ def raiz() -> Path:
38
+ """Pasta a partir da qual os caminhos dos projetos são relativos.
39
+
40
+ As telas antigas usavam os.getcwd() — `quantum start` na raiz do
41
+ repositório. QUANTUM_ADMIN_ROOT permite apontar outra.
42
+ """
43
+ return Path(os.environ.get("QUANTUM_ADMIN_ROOT") or os.getcwd()).resolve()
44
+
45
+
46
+ def pasta_de_configuracao() -> Path:
47
+ """quantum_admin/settings: PIDs, logs, connectors.yaml, global.yaml.
48
+
49
+ A mesma pasta que a biblioteca do backend usa (connector_service,
50
+ settings_service resolvem relativa ao próprio arquivo). As telas antigas
51
+ usavam os.getcwd()/quantum_admin/settings — igual quando `quantum start`
52
+ roda na raiz do repositório, diferente em qualquer outro lugar.
53
+ QUANTUM_ADMIN_SETTINGS_DIR permite apontar outra (testes).
54
+ """
55
+ if os.environ.get("QUANTUM_ADMIN_SETTINGS_DIR"):
56
+ return Path(os.environ["QUANTUM_ADMIN_SETTINGS_DIR"])
57
+ from quantum_admin.backend import connector_service
58
+ return Path(connector_service.SETTINGS_DIR)
59
+
60
+
61
+ def connectors():
62
+ """O ConnectorService do backend (persiste em settings/connectors.yaml)."""
63
+ from quantum_admin.backend.connector_service import get_connector_service
64
+ return get_connector_service()
65
+
66
+
67
+ def status_do_processo(nome_projeto: str) -> dict:
68
+ """{'running': bool, 'pid': int|None} a partir de settings/pids/<nome>.pid.
69
+
70
+ Usa quantum.cli.server_process.pid_alive. A versão das telas (_lib.py)
71
+ chamava OpenProcess no Windows e tomava um handle aberto como processo
72
+ vivo — um processo que já terminou continuava "Running".
73
+ """
74
+ from quantum.cli.server_process import pid_alive
75
+ arquivo = pasta_de_configuracao() / "pids" / f"{nome_projeto}.pid"
76
+ try:
77
+ pid = int(arquivo.read_text(encoding="utf-8").strip())
78
+ except (OSError, ValueError):
79
+ return {"running": False, "pid": None}
80
+ if pid_alive(pid):
81
+ return {"running": True, "pid": pid}
82
+ with contextlib.suppress(OSError):
83
+ arquivo.unlink()
84
+ return {"running": False, "pid": None}