sqlseed-web 0.2.5__tar.gz → 0.2.6__tar.gz

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 (260) hide show
  1. {sqlseed_web-0.2.5 → sqlseed_web-0.2.6}/.gitignore +10 -0
  2. {sqlseed_web-0.2.5 → sqlseed_web-0.2.6}/PKG-INFO +29 -8
  3. {sqlseed_web-0.2.5 → sqlseed_web-0.2.6}/README.md +28 -7
  4. {sqlseed_web-0.2.5 → sqlseed_web-0.2.6}/README.zh-CN.md +28 -9
  5. {sqlseed_web-0.2.5 → sqlseed_web-0.2.6}/src/sqlseed_web/AGENTS.md +2 -0
  6. {sqlseed_web-0.2.5 → sqlseed_web-0.2.6}/src/sqlseed_web/managed_worker.py +70 -17
  7. {sqlseed_web-0.2.5 → sqlseed_web-0.2.6}/src/sqlseed_web/sqlite_target.py +36 -1
  8. {sqlseed_web-0.2.5 → sqlseed_web-0.2.6}/src/sqlseed_web/static/i18n/backend-messages.json +28 -0
  9. {sqlseed_web-0.2.5 → sqlseed_web-0.2.6}/src/sqlseed_web/static/js/design-system.js +10 -6
  10. {sqlseed_web-0.2.5 → sqlseed_web-0.2.6}/src/sqlseed_web/static/js/dropdown.js +1 -1
  11. {sqlseed_web-0.2.5 → sqlseed_web-0.2.6}/src/sqlseed_web/static/js/generation-defaults-control.js +2 -2
  12. {sqlseed_web-0.2.5 → sqlseed_web-0.2.6}/src/sqlseed_web/static/js/i18n/messages/shell.json +1 -1
  13. {sqlseed_web-0.2.5 → sqlseed_web-0.2.6}/src/sqlseed_web/static/js/i18n/messages/workbench.json +14 -0
  14. {sqlseed_web-0.2.5 → sqlseed_web-0.2.6}/src/sqlseed_web/static/js/pages/workbench.js +144 -30
  15. sqlseed_web-0.2.6/src/sqlseed_web/static/js/tab-motion.js +79 -0
  16. {sqlseed_web-0.2.5 → sqlseed_web-0.2.6}/src/sqlseed_web/static/motion.css +8 -0
  17. {sqlseed_web-0.2.5 → sqlseed_web-0.2.6}/src/sqlseed_web/static/navigation.css +3 -2
  18. {sqlseed_web-0.2.5 → sqlseed_web-0.2.6}/src/sqlseed_web/static/runs.css +5 -1
  19. {sqlseed_web-0.2.5 → sqlseed_web-0.2.6}/src/sqlseed_web/static/style.css +67 -39
  20. {sqlseed_web-0.2.5 → sqlseed_web-0.2.6}/src/sqlseed_web/static/workbench.css +48 -9
  21. {sqlseed_web-0.2.5 → sqlseed_web-0.2.6}/src/sqlseed_web/supervised_plugins.py +38 -2
  22. {sqlseed_web-0.2.5 → sqlseed_web-0.2.6}/src/sqlseed_web/supervisor.py +108 -23
  23. {sqlseed_web-0.2.5 → sqlseed_web-0.2.6}/tests/AGENTS.md +1 -0
  24. {sqlseed_web-0.2.5 → sqlseed_web-0.2.6}/tests/test_dropdown.cjs +48 -1
  25. sqlseed_web-0.2.6/tests/test_managed_worker.py +255 -0
  26. {sqlseed_web-0.2.5 → sqlseed_web-0.2.6}/tests/test_settings.cjs +46 -0
  27. {sqlseed_web-0.2.5 → sqlseed_web-0.2.6}/tests/test_supervised_plugins.py +39 -0
  28. sqlseed_web-0.2.6/tests/test_supervisor.py +428 -0
  29. sqlseed_web-0.2.6/tests/test_tab_motion.cjs +277 -0
  30. sqlseed_web-0.2.6/tests/test_workbench_compact.cjs +146 -0
  31. {sqlseed_web-0.2.5 → sqlseed_web-0.2.6}/tests/test_workbench_execution.cjs +195 -0
  32. {sqlseed_web-0.2.5 → sqlseed_web-0.2.6}/tests/test_workbench_guidance.cjs +5 -4
  33. sqlseed_web-0.2.6/tests/test_workbench_run_plan.py +191 -0
  34. {sqlseed_web-0.2.5 → sqlseed_web-0.2.6}/tests/test_workbench_runtime.py +130 -34
  35. {sqlseed_web-0.2.5 → sqlseed_web-0.2.6}/tests/test_workbench_target_identity.py +164 -0
  36. sqlseed_web-0.2.5/src/sqlseed_web/static/js/tab-motion.js +0 -47
  37. sqlseed_web-0.2.5/tests/test_supervisor.py +0 -125
  38. {sqlseed_web-0.2.5 → sqlseed_web-0.2.6}/AGENTS.md +0 -0
  39. {sqlseed_web-0.2.5 → sqlseed_web-0.2.6}/LICENSE +0 -0
  40. {sqlseed_web-0.2.5 → sqlseed_web-0.2.6}/pyproject.toml +0 -0
  41. {sqlseed_web-0.2.5 → sqlseed_web-0.2.6}/src/sqlseed_web/__init__.py +0 -0
  42. {sqlseed_web-0.2.5 → sqlseed_web-0.2.6}/src/sqlseed_web/__main__.py +0 -0
  43. {sqlseed_web-0.2.5 → sqlseed_web-0.2.6}/src/sqlseed_web/_application.py +0 -0
  44. {sqlseed_web-0.2.5 → sqlseed_web-0.2.6}/src/sqlseed_web/_diagnostic_text.py +0 -0
  45. {sqlseed_web-0.2.5 → sqlseed_web-0.2.6}/src/sqlseed_web/_windows_process.py +0 -0
  46. {sqlseed_web-0.2.5 → sqlseed_web-0.2.6}/src/sqlseed_web/ai_settings.py +0 -0
  47. {sqlseed_web-0.2.5 → sqlseed_web-0.2.6}/src/sqlseed_web/api.py +0 -0
  48. {sqlseed_web-0.2.5 → sqlseed_web-0.2.6}/src/sqlseed_web/app.py +0 -0
  49. {sqlseed_web-0.2.5 → sqlseed_web-0.2.6}/src/sqlseed_web/diagnostics.py +0 -0
  50. {sqlseed_web-0.2.5 → sqlseed_web-0.2.6}/src/sqlseed_web/messages.py +0 -0
  51. {sqlseed_web-0.2.5 → sqlseed_web-0.2.6}/src/sqlseed_web/operation_errors.py +0 -0
  52. {sqlseed_web-0.2.5 → sqlseed_web-0.2.6}/src/sqlseed_web/plugin_environment.py +0 -0
  53. {sqlseed_web-0.2.5 → sqlseed_web-0.2.6}/src/sqlseed_web/plugin_management.py +0 -0
  54. {sqlseed_web-0.2.5 → sqlseed_web-0.2.6}/src/sqlseed_web/plugin_process.py +0 -0
  55. {sqlseed_web-0.2.5 → sqlseed_web-0.2.6}/src/sqlseed_web/plugin_updates.py +0 -0
  56. {sqlseed_web-0.2.5 → sqlseed_web-0.2.6}/src/sqlseed_web/runtime_lifecycle.py +0 -0
  57. {sqlseed_web-0.2.5 → sqlseed_web-0.2.6}/src/sqlseed_web/runtime_session.py +0 -0
  58. {sqlseed_web-0.2.5 → sqlseed_web-0.2.6}/src/sqlseed_web/settings_environment.py +0 -0
  59. {sqlseed_web-0.2.5 → sqlseed_web-0.2.6}/src/sqlseed_web/settings_updates.py +0 -0
  60. {sqlseed_web-0.2.5 → sqlseed_web-0.2.6}/src/sqlseed_web/state.py +0 -0
  61. {sqlseed_web-0.2.5 → sqlseed_web-0.2.6}/src/sqlseed_web/static/AGENTS.md +0 -0
  62. {sqlseed_web-0.2.5 → sqlseed_web-0.2.6}/src/sqlseed_web/static/ai.css +0 -0
  63. {sqlseed_web-0.2.5 → sqlseed_web-0.2.6}/src/sqlseed_web/static/configs.css +0 -0
  64. {sqlseed_web-0.2.5 → sqlseed_web-0.2.6}/src/sqlseed_web/static/date-picker.css +0 -0
  65. {sqlseed_web-0.2.5 → sqlseed_web-0.2.6}/src/sqlseed_web/static/design-system.css +0 -0
  66. {sqlseed_web-0.2.5 → sqlseed_web-0.2.6}/src/sqlseed_web/static/design-system.html +0 -0
  67. {sqlseed_web-0.2.5 → sqlseed_web-0.2.6}/src/sqlseed_web/static/disclosure.css +0 -0
  68. {sqlseed_web-0.2.5 → sqlseed_web-0.2.6}/src/sqlseed_web/static/fonts/chill-round-gothic/ChillRoundGothic-Medium.woff2 +0 -0
  69. {sqlseed_web-0.2.5 → sqlseed_web-0.2.6}/src/sqlseed_web/static/fonts/chill-round-gothic/ChillRoundGothic-Regular.woff2 +0 -0
  70. {sqlseed_web-0.2.5 → sqlseed_web-0.2.6}/src/sqlseed_web/static/fonts/chill-round-gothic/License.txt +0 -0
  71. {sqlseed_web-0.2.5 → sqlseed_web-0.2.6}/src/sqlseed_web/static/fonts/chill-round-gothic/README.md +0 -0
  72. {sqlseed_web-0.2.5 → sqlseed_web-0.2.6}/src/sqlseed_web/static/graph-clarity.css +0 -0
  73. {sqlseed_web-0.2.5 → sqlseed_web-0.2.6}/src/sqlseed_web/static/index.html +0 -0
  74. {sqlseed_web-0.2.5 → sqlseed_web-0.2.6}/src/sqlseed_web/static/js/api.js +0 -0
  75. {sqlseed_web-0.2.5 → sqlseed_web-0.2.6}/src/sqlseed_web/static/js/app.js +0 -0
  76. {sqlseed_web-0.2.5 → sqlseed_web-0.2.6}/src/sqlseed_web/static/js/filepicker.js +0 -0
  77. {sqlseed_web-0.2.5 → sqlseed_web-0.2.6}/src/sqlseed_web/static/js/generation-defaults.js +0 -0
  78. {sqlseed_web-0.2.5 → sqlseed_web-0.2.6}/src/sqlseed_web/static/js/genform.js +0 -0
  79. {sqlseed_web-0.2.5 → sqlseed_web-0.2.6}/src/sqlseed_web/static/js/i18n/messages/assistant.js +0 -0
  80. {sqlseed_web-0.2.5 → sqlseed_web-0.2.6}/src/sqlseed_web/static/js/i18n/messages/assistant.json +0 -0
  81. {sqlseed_web-0.2.5 → sqlseed_web-0.2.6}/src/sqlseed_web/static/js/i18n/messages/components.js +0 -0
  82. {sqlseed_web-0.2.5 → sqlseed_web-0.2.6}/src/sqlseed_web/static/js/i18n/messages/components.json +0 -0
  83. {sqlseed_web-0.2.5 → sqlseed_web-0.2.6}/src/sqlseed_web/static/js/i18n/messages/configurations.js +0 -0
  84. {sqlseed_web-0.2.5 → sqlseed_web-0.2.6}/src/sqlseed_web/static/js/i18n/messages/configurations.json +0 -0
  85. {sqlseed_web-0.2.5 → sqlseed_web-0.2.6}/src/sqlseed_web/static/js/i18n/messages/datePicker.js +0 -0
  86. {sqlseed_web-0.2.5 → sqlseed_web-0.2.6}/src/sqlseed_web/static/js/i18n/messages/datePicker.json +0 -0
  87. {sqlseed_web-0.2.5 → sqlseed_web-0.2.6}/src/sqlseed_web/static/js/i18n/messages/editor.js +0 -0
  88. {sqlseed_web-0.2.5 → sqlseed_web-0.2.6}/src/sqlseed_web/static/js/i18n/messages/editor.json +0 -0
  89. {sqlseed_web-0.2.5 → sqlseed_web-0.2.6}/src/sqlseed_web/static/js/i18n/messages/flow.js +0 -0
  90. {sqlseed_web-0.2.5 → sqlseed_web-0.2.6}/src/sqlseed_web/static/js/i18n/messages/flow.json +0 -0
  91. {sqlseed_web-0.2.5 → sqlseed_web-0.2.6}/src/sqlseed_web/static/js/i18n/messages/graph.js +0 -0
  92. {sqlseed_web-0.2.5 → sqlseed_web-0.2.6}/src/sqlseed_web/static/js/i18n/messages/graph.json +0 -0
  93. {sqlseed_web-0.2.5 → sqlseed_web-0.2.6}/src/sqlseed_web/static/js/i18n/messages/labels.js +0 -0
  94. {sqlseed_web-0.2.5 → sqlseed_web-0.2.6}/src/sqlseed_web/static/js/i18n/messages/labels.json +0 -0
  95. {sqlseed_web-0.2.5 → sqlseed_web-0.2.6}/src/sqlseed_web/static/js/i18n/messages/preview.js +0 -0
  96. {sqlseed_web-0.2.5 → sqlseed_web-0.2.6}/src/sqlseed_web/static/js/i18n/messages/preview.json +0 -0
  97. {sqlseed_web-0.2.5 → sqlseed_web-0.2.6}/src/sqlseed_web/static/js/i18n/messages/providerGuide.js +0 -0
  98. {sqlseed_web-0.2.5 → sqlseed_web-0.2.6}/src/sqlseed_web/static/js/i18n/messages/providerGuide.json +0 -0
  99. {sqlseed_web-0.2.5 → sqlseed_web-0.2.6}/src/sqlseed_web/static/js/i18n/messages/runs.js +0 -0
  100. {sqlseed_web-0.2.5 → sqlseed_web-0.2.6}/src/sqlseed_web/static/js/i18n/messages/runs.json +0 -0
  101. {sqlseed_web-0.2.5 → sqlseed_web-0.2.6}/src/sqlseed_web/static/js/i18n/messages/settings.js +0 -0
  102. {sqlseed_web-0.2.5 → sqlseed_web-0.2.6}/src/sqlseed_web/static/js/i18n/messages/settings.json +0 -0
  103. {sqlseed_web-0.2.5 → sqlseed_web-0.2.6}/src/sqlseed_web/static/js/i18n/messages/shell.js +0 -0
  104. {sqlseed_web-0.2.5 → sqlseed_web-0.2.6}/src/sqlseed_web/static/js/i18n/messages/workbench.js +0 -0
  105. {sqlseed_web-0.2.5 → sqlseed_web-0.2.6}/src/sqlseed_web/static/js/i18n.js +0 -0
  106. {sqlseed_web-0.2.5 → sqlseed_web-0.2.6}/src/sqlseed_web/static/js/labels.js +0 -0
  107. {sqlseed_web-0.2.5 → sqlseed_web-0.2.6}/src/sqlseed_web/static/js/pages/browse.js +0 -0
  108. {sqlseed_web-0.2.5 → sqlseed_web-0.2.6}/src/sqlseed_web/static/js/pages/configs.js +0 -0
  109. {sqlseed_web-0.2.5 → sqlseed_web-0.2.6}/src/sqlseed_web/static/js/pages/connect.js +0 -0
  110. {sqlseed_web-0.2.5 → sqlseed_web-0.2.6}/src/sqlseed_web/static/js/pages/heal.js +0 -0
  111. {sqlseed_web-0.2.5 → sqlseed_web-0.2.6}/src/sqlseed_web/static/js/pages/meta.js +0 -0
  112. {sqlseed_web-0.2.5 → sqlseed_web-0.2.6}/src/sqlseed_web/static/js/pages/runs.js +0 -0
  113. {sqlseed_web-0.2.5 → sqlseed_web-0.2.6}/src/sqlseed_web/static/js/pages/settings.js +0 -0
  114. {sqlseed_web-0.2.5 → sqlseed_web-0.2.6}/src/sqlseed_web/static/js/pages/wizard.js +0 -0
  115. {sqlseed_web-0.2.5 → sqlseed_web-0.2.6}/src/sqlseed_web/static/js/segment-motion.js +0 -0
  116. {sqlseed_web-0.2.5 → sqlseed_web-0.2.6}/src/sqlseed_web/static/js/theme-control.js +0 -0
  117. {sqlseed_web-0.2.5 → sqlseed_web-0.2.6}/src/sqlseed_web/static/js/theme.js +0 -0
  118. {sqlseed_web-0.2.5 → sqlseed_web-0.2.6}/src/sqlseed_web/static/js/tree.js +0 -0
  119. {sqlseed_web-0.2.5 → sqlseed_web-0.2.6}/src/sqlseed_web/static/js/update-check-control.js +0 -0
  120. {sqlseed_web-0.2.5 → sqlseed_web-0.2.6}/src/sqlseed_web/static/js/workbench/ai-adjustment.js +0 -0
  121. {sqlseed_web-0.2.5 → sqlseed_web-0.2.6}/src/sqlseed_web/static/js/workbench/ai-eligibility.js +0 -0
  122. {sqlseed_web-0.2.5 → sqlseed_web-0.2.6}/src/sqlseed_web/static/js/workbench/ai-handoff.js +0 -0
  123. {sqlseed_web-0.2.5 → sqlseed_web-0.2.6}/src/sqlseed_web/static/js/workbench/ai-stream.js +0 -0
  124. {sqlseed_web-0.2.5 → sqlseed_web-0.2.6}/src/sqlseed_web/static/js/workbench/ai.js +0 -0
  125. {sqlseed_web-0.2.5 → sqlseed_web-0.2.6}/src/sqlseed_web/static/js/workbench/clear-recovery.js +0 -0
  126. {sqlseed_web-0.2.5 → sqlseed_web-0.2.6}/src/sqlseed_web/static/js/workbench/connection.js +0 -0
  127. {sqlseed_web-0.2.5 → sqlseed_web-0.2.6}/src/sqlseed_web/static/js/workbench/date-picker.js +0 -0
  128. {sqlseed_web-0.2.5 → sqlseed_web-0.2.6}/src/sqlseed_web/static/js/workbench/dependency-view.js +0 -0
  129. {sqlseed_web-0.2.5 → sqlseed_web-0.2.6}/src/sqlseed_web/static/js/workbench/editor.js +0 -0
  130. {sqlseed_web-0.2.5 → sqlseed_web-0.2.6}/src/sqlseed_web/static/js/workbench/focus.js +0 -0
  131. {sqlseed_web-0.2.5 → sqlseed_web-0.2.6}/src/sqlseed_web/static/js/workbench/graph-layout.js +0 -0
  132. {sqlseed_web-0.2.5 → sqlseed_web-0.2.6}/src/sqlseed_web/static/js/workbench/graph.js +0 -0
  133. {sqlseed_web-0.2.5 → sqlseed_web-0.2.6}/src/sqlseed_web/static/js/workbench/guidance.js +0 -0
  134. {sqlseed_web-0.2.5 → sqlseed_web-0.2.6}/src/sqlseed_web/static/js/workbench/model.js +0 -0
  135. {sqlseed_web-0.2.5 → sqlseed_web-0.2.6}/src/sqlseed_web/static/js/workbench/plugin-management.js +0 -0
  136. {sqlseed_web-0.2.5 → sqlseed_web-0.2.6}/src/sqlseed_web/static/js/workbench/preview-scroll-layout.js +0 -0
  137. {sqlseed_web-0.2.5 → sqlseed_web-0.2.6}/src/sqlseed_web/static/js/workbench/preview.js +0 -0
  138. {sqlseed_web-0.2.5 → sqlseed_web-0.2.6}/src/sqlseed_web/static/js/workbench/provider-guide.js +0 -0
  139. {sqlseed_web-0.2.5 → sqlseed_web-0.2.6}/src/sqlseed_web/static/js/workbench/recovery.js +0 -0
  140. {sqlseed_web-0.2.5 → sqlseed_web-0.2.6}/src/sqlseed_web/static/js/workbench/scroll-lock.js +0 -0
  141. {sqlseed_web-0.2.5 → sqlseed_web-0.2.6}/src/sqlseed_web/static/js/workbench/session.js +0 -0
  142. {sqlseed_web-0.2.5 → sqlseed_web-0.2.6}/src/sqlseed_web/static/js/workbench/table-data.js +0 -0
  143. {sqlseed_web-0.2.5 → sqlseed_web-0.2.6}/src/sqlseed_web/static/js/workbench/ui.js +0 -0
  144. {sqlseed_web-0.2.5 → sqlseed_web-0.2.6}/src/sqlseed_web/static/preview.css +0 -0
  145. {sqlseed_web-0.2.5 → sqlseed_web-0.2.6}/src/sqlseed_web/static/scrollbars.css +0 -0
  146. {sqlseed_web-0.2.5 → sqlseed_web-0.2.6}/src/sqlseed_web/static/settings.css +0 -0
  147. {sqlseed_web-0.2.5 → sqlseed_web-0.2.6}/src/sqlseed_web/static/table-data.css +0 -0
  148. {sqlseed_web-0.2.5 → sqlseed_web-0.2.6}/src/sqlseed_web/workbench.py +0 -0
  149. {sqlseed_web-0.2.5 → sqlseed_web-0.2.6}/src/sqlseed_web/workbench_ai.py +0 -0
  150. {sqlseed_web-0.2.5 → sqlseed_web-0.2.6}/src/sqlseed_web/workbench_ai_relations.py +0 -0
  151. {sqlseed_web-0.2.5 → sqlseed_web-0.2.6}/src/sqlseed_web/workbench_ai_stream.py +0 -0
  152. {sqlseed_web-0.2.5 → sqlseed_web-0.2.6}/src/sqlseed_web/workbench_cycles.py +0 -0
  153. {sqlseed_web-0.2.5 → sqlseed_web-0.2.6}/src/sqlseed_web/workbench_data.py +0 -0
  154. {sqlseed_web-0.2.5 → sqlseed_web-0.2.6}/src/sqlseed_web/workbench_execution.py +0 -0
  155. {sqlseed_web-0.2.5 → sqlseed_web-0.2.6}/src/sqlseed_web/workbench_runtime.py +0 -0
  156. {sqlseed_web-0.2.5 → sqlseed_web-0.2.6}/src/sqlseed_web/workbench_schema.py +0 -0
  157. {sqlseed_web-0.2.5 → sqlseed_web-0.2.6}/src/sqlseed_web/workbench_store.py +0 -0
  158. {sqlseed_web-0.2.5 → sqlseed_web-0.2.6}/src/sqlseed_web/worker_control.py +0 -0
  159. {sqlseed_web-0.2.5 → sqlseed_web-0.2.6}/tests/complex_business_graph.json +0 -0
  160. {sqlseed_web-0.2.5 → sqlseed_web-0.2.6}/tests/complex_graph_fixture.py +0 -0
  161. {sqlseed_web-0.2.5 → sqlseed_web-0.2.6}/tests/component_test_support.py +0 -0
  162. {sqlseed_web-0.2.5 → sqlseed_web-0.2.6}/tests/conftest.py +0 -0
  163. {sqlseed_web-0.2.5 → sqlseed_web-0.2.6}/tests/frontend_helpers.cjs +0 -0
  164. {sqlseed_web-0.2.5 → sqlseed_web-0.2.6}/tests/test_ai_adjustment.cjs +0 -0
  165. {sqlseed_web-0.2.5 → sqlseed_web-0.2.6}/tests/test_ai_eligibility.cjs +0 -0
  166. {sqlseed_web-0.2.5 → sqlseed_web-0.2.6}/tests/test_api.py +0 -0
  167. {sqlseed_web-0.2.5 → sqlseed_web-0.2.6}/tests/test_api_ai_secrets.py +0 -0
  168. {sqlseed_web-0.2.5 → sqlseed_web-0.2.6}/tests/test_api_regressions.py +0 -0
  169. {sqlseed_web-0.2.5 → sqlseed_web-0.2.6}/tests/test_app_shell.cjs +0 -0
  170. {sqlseed_web-0.2.5 → sqlseed_web-0.2.6}/tests/test_backend_messages.py +0 -0
  171. {sqlseed_web-0.2.5 → sqlseed_web-0.2.6}/tests/test_browse.cjs +0 -0
  172. {sqlseed_web-0.2.5 → sqlseed_web-0.2.6}/tests/test_complex_business_graph.cjs +0 -0
  173. {sqlseed_web-0.2.5 → sqlseed_web-0.2.6}/tests/test_complex_graph_fixture.py +0 -0
  174. {sqlseed_web-0.2.5 → sqlseed_web-0.2.6}/tests/test_component_availability.py +0 -0
  175. {sqlseed_web-0.2.5 → sqlseed_web-0.2.6}/tests/test_component_test_support.py +0 -0
  176. {sqlseed_web-0.2.5 → sqlseed_web-0.2.6}/tests/test_configs.cjs +0 -0
  177. {sqlseed_web-0.2.5 → sqlseed_web-0.2.6}/tests/test_connection.cjs +0 -0
  178. {sqlseed_web-0.2.5 → sqlseed_web-0.2.6}/tests/test_connection_existing_file.py +0 -0
  179. {sqlseed_web-0.2.5 → sqlseed_web-0.2.6}/tests/test_date_picker.cjs +0 -0
  180. {sqlseed_web-0.2.5 → sqlseed_web-0.2.6}/tests/test_dependency_groups.cjs +0 -0
  181. {sqlseed_web-0.2.5 → sqlseed_web-0.2.6}/tests/test_disclosure_focus.cjs +0 -0
  182. {sqlseed_web-0.2.5 → sqlseed_web-0.2.6}/tests/test_filepicker.cjs +0 -0
  183. {sqlseed_web-0.2.5 → sqlseed_web-0.2.6}/tests/test_generation_defaults.cjs +0 -0
  184. {sqlseed_web-0.2.5 → sqlseed_web-0.2.6}/tests/test_genform.cjs +0 -0
  185. {sqlseed_web-0.2.5 → sqlseed_web-0.2.6}/tests/test_graph_layout_order.cjs +0 -0
  186. {sqlseed_web-0.2.5 → sqlseed_web-0.2.6}/tests/test_graph_routing.cjs +0 -0
  187. {sqlseed_web-0.2.5 → sqlseed_web-0.2.6}/tests/test_hardening_boundaries.py +0 -0
  188. {sqlseed_web-0.2.5 → sqlseed_web-0.2.6}/tests/test_i18n.cjs +0 -0
  189. {sqlseed_web-0.2.5 → sqlseed_web-0.2.6}/tests/test_i18n_catalog.cjs +0 -0
  190. {sqlseed_web-0.2.5 → sqlseed_web-0.2.6}/tests/test_i18n_component_paths.py +0 -0
  191. {sqlseed_web-0.2.5 → sqlseed_web-0.2.6}/tests/test_i18n_validation_paths.py +0 -0
  192. {sqlseed_web-0.2.5 → sqlseed_web-0.2.6}/tests/test_job_completion.py +0 -0
  193. {sqlseed_web-0.2.5 → sqlseed_web-0.2.6}/tests/test_legacy_connect.cjs +0 -0
  194. {sqlseed_web-0.2.5 → sqlseed_web-0.2.6}/tests/test_legacy_page_async.cjs +0 -0
  195. {sqlseed_web-0.2.5 → sqlseed_web-0.2.6}/tests/test_modal_scroll.cjs +0 -0
  196. {sqlseed_web-0.2.5 → sqlseed_web-0.2.6}/tests/test_navigation_motion.cjs +0 -0
  197. {sqlseed_web-0.2.5 → sqlseed_web-0.2.6}/tests/test_plugin_cleanup.py +0 -0
  198. {sqlseed_web-0.2.5 → sqlseed_web-0.2.6}/tests/test_plugin_management.cjs +0 -0
  199. {sqlseed_web-0.2.5 → sqlseed_web-0.2.6}/tests/test_plugin_management.py +0 -0
  200. {sqlseed_web-0.2.5 → sqlseed_web-0.2.6}/tests/test_plugin_process.py +0 -0
  201. {sqlseed_web-0.2.5 → sqlseed_web-0.2.6}/tests/test_plugin_updates.py +0 -0
  202. {sqlseed_web-0.2.5 → sqlseed_web-0.2.6}/tests/test_preview_editing.cjs +0 -0
  203. {sqlseed_web-0.2.5 → sqlseed_web-0.2.6}/tests/test_preview_scroll_layout.cjs +0 -0
  204. {sqlseed_web-0.2.5 → sqlseed_web-0.2.6}/tests/test_provider_guide.cjs +0 -0
  205. {sqlseed_web-0.2.5 → sqlseed_web-0.2.6}/tests/test_rule_usability.cjs +0 -0
  206. {sqlseed_web-0.2.5 → sqlseed_web-0.2.6}/tests/test_run_recovery.cjs +0 -0
  207. {sqlseed_web-0.2.5 → sqlseed_web-0.2.6}/tests/test_runs.cjs +0 -0
  208. {sqlseed_web-0.2.5 → sqlseed_web-0.2.6}/tests/test_runtime_lifecycle.py +0 -0
  209. {sqlseed_web-0.2.5 → sqlseed_web-0.2.6}/tests/test_runtime_session.py +0 -0
  210. {sqlseed_web-0.2.5 → sqlseed_web-0.2.6}/tests/test_segment_motion.cjs +0 -0
  211. {sqlseed_web-0.2.5 → sqlseed_web-0.2.6}/tests/test_settings_update_lifecycle.py +0 -0
  212. {sqlseed_web-0.2.5 → sqlseed_web-0.2.6}/tests/test_settings_updates.py +0 -0
  213. {sqlseed_web-0.2.5 → sqlseed_web-0.2.6}/tests/test_table_data.cjs +0 -0
  214. {sqlseed_web-0.2.5 → sqlseed_web-0.2.6}/tests/test_theme.cjs +0 -0
  215. {sqlseed_web-0.2.5 → sqlseed_web-0.2.6}/tests/test_web_request_security.py +0 -0
  216. {sqlseed_web-0.2.5 → sqlseed_web-0.2.6}/tests/test_web_settings.py +0 -0
  217. {sqlseed_web-0.2.5 → sqlseed_web-0.2.6}/tests/test_windows_environment.py +0 -0
  218. {sqlseed_web-0.2.5 → sqlseed_web-0.2.6}/tests/test_windows_guard.py +0 -0
  219. {sqlseed_web-0.2.5 → sqlseed_web-0.2.6}/tests/test_windows_plugin_lifecycle.py +0 -0
  220. {sqlseed_web-0.2.5 → sqlseed_web-0.2.6}/tests/test_wizard.cjs +0 -0
  221. {sqlseed_web-0.2.5 → sqlseed_web-0.2.6}/tests/test_workbench_acceptance.py +0 -0
  222. {sqlseed_web-0.2.5 → sqlseed_web-0.2.6}/tests/test_workbench_ai.cjs +0 -0
  223. {sqlseed_web-0.2.5 → sqlseed_web-0.2.6}/tests/test_workbench_ai.py +0 -0
  224. {sqlseed_web-0.2.5 → sqlseed_web-0.2.6}/tests/test_workbench_ai_handoff.cjs +0 -0
  225. {sqlseed_web-0.2.5 → sqlseed_web-0.2.6}/tests/test_workbench_ai_integration.cjs +0 -0
  226. {sqlseed_web-0.2.5 → sqlseed_web-0.2.6}/tests/test_workbench_ai_progress.cjs +0 -0
  227. {sqlseed_web-0.2.5 → sqlseed_web-0.2.6}/tests/test_workbench_ai_relations.py +0 -0
  228. {sqlseed_web-0.2.5 → sqlseed_web-0.2.6}/tests/test_workbench_ai_stream.cjs +0 -0
  229. {sqlseed_web-0.2.5 → sqlseed_web-0.2.6}/tests/test_workbench_async_boundaries.cjs +0 -0
  230. {sqlseed_web-0.2.5 → sqlseed_web-0.2.6}/tests/test_workbench_busy.cjs +0 -0
  231. {sqlseed_web-0.2.5 → sqlseed_web-0.2.6}/tests/test_workbench_capability_limits.cjs +0 -0
  232. {sqlseed_web-0.2.5 → sqlseed_web-0.2.6}/tests/test_workbench_clear_recovery.cjs +0 -0
  233. {sqlseed_web-0.2.5 → sqlseed_web-0.2.6}/tests/test_workbench_concurrency.py +0 -0
  234. {sqlseed_web-0.2.5 → sqlseed_web-0.2.6}/tests/test_workbench_configs.py +0 -0
  235. {sqlseed_web-0.2.5 → sqlseed_web-0.2.6}/tests/test_workbench_connection_routing.cjs +0 -0
  236. {sqlseed_web-0.2.5 → sqlseed_web-0.2.6}/tests/test_workbench_context.cjs +0 -0
  237. {sqlseed_web-0.2.5 → sqlseed_web-0.2.6}/tests/test_workbench_data.cjs +0 -0
  238. {sqlseed_web-0.2.5 → sqlseed_web-0.2.6}/tests/test_workbench_data.py +0 -0
  239. {sqlseed_web-0.2.5 → sqlseed_web-0.2.6}/tests/test_workbench_documents.cjs +0 -0
  240. {sqlseed_web-0.2.5 → sqlseed_web-0.2.6}/tests/test_workbench_editor.cjs +0 -0
  241. {sqlseed_web-0.2.5 → sqlseed_web-0.2.6}/tests/test_workbench_empty_schema.cjs +0 -0
  242. {sqlseed_web-0.2.5 → sqlseed_web-0.2.6}/tests/test_workbench_execution.py +0 -0
  243. {sqlseed_web-0.2.5 → sqlseed_web-0.2.6}/tests/test_workbench_existing_cycles.py +0 -0
  244. {sqlseed_web-0.2.5 → sqlseed_web-0.2.6}/tests/test_workbench_graph.cjs +0 -0
  245. {sqlseed_web-0.2.5 → sqlseed_web-0.2.6}/tests/test_workbench_graph_checks.cjs +0 -0
  246. {sqlseed_web-0.2.5 → sqlseed_web-0.2.6}/tests/test_workbench_model.cjs +0 -0
  247. {sqlseed_web-0.2.5 → sqlseed_web-0.2.6}/tests/test_workbench_page.cjs +0 -0
  248. {sqlseed_web-0.2.5 → sqlseed_web-0.2.6}/tests/test_workbench_postgresql_cycles.py +0 -0
  249. {sqlseed_web-0.2.5 → sqlseed_web-0.2.6}/tests/test_workbench_preview.cjs +0 -0
  250. {sqlseed_web-0.2.5 → sqlseed_web-0.2.6}/tests/test_workbench_providers.cjs +0 -0
  251. {sqlseed_web-0.2.5 → sqlseed_web-0.2.6}/tests/test_workbench_review.cjs +0 -0
  252. {sqlseed_web-0.2.5 → sqlseed_web-0.2.6}/tests/test_workbench_sample_budget.py +0 -0
  253. {sqlseed_web-0.2.5 → sqlseed_web-0.2.6}/tests/test_workbench_schema.py +0 -0
  254. {sqlseed_web-0.2.5 → sqlseed_web-0.2.6}/tests/test_workbench_session.cjs +0 -0
  255. {sqlseed_web-0.2.5 → sqlseed_web-0.2.6}/tests/test_workbench_store.py +0 -0
  256. {sqlseed_web-0.2.5 → sqlseed_web-0.2.6}/tests/test_workbench_usability.cjs +0 -0
  257. {sqlseed_web-0.2.5 → sqlseed_web-0.2.6}/tests/test_workbench_v8.cjs +0 -0
  258. {sqlseed_web-0.2.5 → sqlseed_web-0.2.6}/tests/test_worker_control.py +0 -0
  259. {sqlseed_web-0.2.5 → sqlseed_web-0.2.6}/tests/workbench_harness.cjs +0 -0
  260. {sqlseed_web-0.2.5 → sqlseed_web-0.2.6}/tests/workbench_test_helpers.py +0 -0
@@ -59,6 +59,16 @@ dmypy.json
59
59
  *.db
60
60
  *.sqlite
61
61
  *.sqlite3
62
+ # SQLite runtime sidecars
63
+ *.db-wal
64
+ *.db-shm
65
+ *.db-journal
66
+ *.sqlite-wal
67
+ *.sqlite-shm
68
+ *.sqlite-journal
69
+ *.sqlite3-wal
70
+ *.sqlite3-shm
71
+ *.sqlite3-journal
62
72
  .sqlseed_cache/
63
73
  snapshots/
64
74
  .env
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.5
2
2
  Name: sqlseed-web
3
- Version: 0.2.5
3
+ Version: 0.2.6
4
4
  Summary: Local sqlseed workbench for SQLite and PostgreSQL rules, previews, generation and optional AI suggestions
5
5
  Project-URL: Homepage, https://github.com/sunbos/sqlseed
6
6
  Project-URL: Repository, https://github.com/sunbos/sqlseed/tree/main/plugins/sqlseed-web
@@ -30,19 +30,40 @@ A local browser workbench for declarative SQLite and PostgreSQL test data genera
30
30
  Connect a database, edit field rules, preview samples, inspect dependencies and review
31
31
  generation results. The Python core runs offline; AI suggestions are optional.
32
32
 
33
+ ## A look at the workbench
34
+
35
+ ![sqlseed Web in English: selected tables and a four-table relationship graph in the light theme](https://raw.githubusercontent.com/sunbos/sqlseed/992ba0e733d5b41f73e37b0a9d02d573d6e2bb23/docs/assets/screenshots/web-workbench-en-light.png)
36
+
37
+ The actual 0.2.5 interface with the repository's fictional SQLite order example.
38
+ [Open the full-size PNG](https://raw.githubusercontent.com/sunbos/sqlseed/992ba0e733d5b41f73e37b0a9d02d573d6e2bb23/docs/assets/screenshots/web-workbench-en-light.png)
39
+ or [see the read-only sample preview in the dark theme](https://raw.githubusercontent.com/sunbos/sqlseed/992ba0e733d5b41f73e37b0a9d02d573d6e2bb23/docs/assets/screenshots/web-workbench-en-dark.png).
40
+
41
+ Connect an existing database, select tables and row counts, review field rules and
42
+ dependencies, preview samples, then confirm the generation plan.
43
+
44
+ | Page | What you can do |
45
+ | --- | --- |
46
+ | Workbench | Edit rules, inspect the relationship graph, preview samples without writing, and confirm generation. |
47
+ | Configs | Save reusable rules, import or export YAML, and reopen configurations for the matching database. |
48
+ | Runs | Review per-table outcomes, committed row counts, and the configuration snapshot used for a run. |
49
+ | Settings | Choose generation defaults, light/dark appearance, optional AI settings, and available components. |
50
+
51
+ The [order workflow example](https://github.com/sunbos/sqlseed/tree/main/examples/order_workflow)
52
+ includes the schema, rules, and instructions for creating your own disposable demo.
53
+
33
54
  ## Installation
34
55
 
35
- These instructions target version 0.2.5. Check [Releases](https://github.com/sunbos/sqlseed/releases)
56
+ These instructions target version 0.2.6. Check [Releases](https://github.com/sunbos/sqlseed/releases)
36
57
  for publication status; use the source installation below to test an unpublished candidate.
37
58
  Use a Python 3.10+ virtual environment:
38
59
 
39
60
  ```bash
40
- python -m pip install "sqlseed==0.2.5" "sqlseed-web==0.2.5"
61
+ python -m pip install "sqlseed==0.2.6" "sqlseed-web==0.2.6"
41
62
  sqlseed-web
42
63
  ```
43
64
 
44
65
  Open `http://127.0.0.1:8630`. The wheel includes the frontend; no Node or npm build
45
- is needed to use the app. For PostgreSQL, also install `"sqlseed[postgres]==0.2.5"`.
66
+ is needed to use the app. For PostgreSQL, also install `"sqlseed[postgres]==0.2.6"`.
46
67
  Core 0.2.4 and older lack the shared connection and diagnostic interfaces required by this version.
47
68
 
48
69
  For development, install local Core and Web together from the repository root:
@@ -51,13 +72,13 @@ For development, install local Core and Web together from the repository root:
51
72
  python -m pip install -e . -e ./plugins/sqlseed-web
52
73
  ```
53
74
 
54
- Version 0.2.5 and its source candidates require Core `>=0.2.5.dev0,<0.3` for
75
+ Version 0.2.6 and its source candidates require Core `>=0.2.5.dev0,<0.3` for
55
76
  connection-target parsing and diagnostic redaction. Install matching Core and Web
56
77
  versions; do not disable dependency checks to keep an older Core.
57
78
 
58
79
  ## Interface language
59
80
 
60
- Version 0.2.5 offers **简体中文 / English** in the top bar.
81
+ Version 0.2.6 offers **简体中文 / English** in the top bar.
61
82
  The browser remembers your choice and synchronizes it with other tabs on the same
62
83
  origin. Without a saved choice, the first supported browser language is used,
63
84
  falling back to English. If storage is unavailable, switching still works for the
@@ -89,10 +110,10 @@ install local Core, CLI, AI, and Web together in the same resolution:
89
110
  python -m pip install -e . -e ./plugins/sqlseed-cli -e ./plugins/sqlseed-ai -e ./plugins/sqlseed-web
90
111
  ```
91
112
 
92
- For version 0.2.5, `python -m pip install "sqlseed-web[ai]==0.2.5"` installs
113
+ For version 0.2.6, `python -m pip install "sqlseed-web[ai]==0.2.6"` installs
93
114
  the optional AI component. The page does not fall back to an incompatible older release.
94
115
 
95
- The version 0.2.5 default launcher manages optional packages
116
+ The version 0.2.6 default launcher manages optional packages
96
117
  in supported writable Windows, macOS and Linux virtual environments and restores
97
118
  the service automatically. Externally hosted apps and read-only/system environments
98
119
  can use the workbench but do not offer in-page package changes. Missing components
@@ -6,19 +6,40 @@ A local browser workbench for declarative SQLite and PostgreSQL test data genera
6
6
  Connect a database, edit field rules, preview samples, inspect dependencies and review
7
7
  generation results. The Python core runs offline; AI suggestions are optional.
8
8
 
9
+ ## A look at the workbench
10
+
11
+ ![sqlseed Web in English: selected tables and a four-table relationship graph in the light theme](https://raw.githubusercontent.com/sunbos/sqlseed/992ba0e733d5b41f73e37b0a9d02d573d6e2bb23/docs/assets/screenshots/web-workbench-en-light.png)
12
+
13
+ The actual 0.2.5 interface with the repository's fictional SQLite order example.
14
+ [Open the full-size PNG](https://raw.githubusercontent.com/sunbos/sqlseed/992ba0e733d5b41f73e37b0a9d02d573d6e2bb23/docs/assets/screenshots/web-workbench-en-light.png)
15
+ or [see the read-only sample preview in the dark theme](https://raw.githubusercontent.com/sunbos/sqlseed/992ba0e733d5b41f73e37b0a9d02d573d6e2bb23/docs/assets/screenshots/web-workbench-en-dark.png).
16
+
17
+ Connect an existing database, select tables and row counts, review field rules and
18
+ dependencies, preview samples, then confirm the generation plan.
19
+
20
+ | Page | What you can do |
21
+ | --- | --- |
22
+ | Workbench | Edit rules, inspect the relationship graph, preview samples without writing, and confirm generation. |
23
+ | Configs | Save reusable rules, import or export YAML, and reopen configurations for the matching database. |
24
+ | Runs | Review per-table outcomes, committed row counts, and the configuration snapshot used for a run. |
25
+ | Settings | Choose generation defaults, light/dark appearance, optional AI settings, and available components. |
26
+
27
+ The [order workflow example](https://github.com/sunbos/sqlseed/tree/main/examples/order_workflow)
28
+ includes the schema, rules, and instructions for creating your own disposable demo.
29
+
9
30
  ## Installation
10
31
 
11
- These instructions target version 0.2.5. Check [Releases](https://github.com/sunbos/sqlseed/releases)
32
+ These instructions target version 0.2.6. Check [Releases](https://github.com/sunbos/sqlseed/releases)
12
33
  for publication status; use the source installation below to test an unpublished candidate.
13
34
  Use a Python 3.10+ virtual environment:
14
35
 
15
36
  ```bash
16
- python -m pip install "sqlseed==0.2.5" "sqlseed-web==0.2.5"
37
+ python -m pip install "sqlseed==0.2.6" "sqlseed-web==0.2.6"
17
38
  sqlseed-web
18
39
  ```
19
40
 
20
41
  Open `http://127.0.0.1:8630`. The wheel includes the frontend; no Node or npm build
21
- is needed to use the app. For PostgreSQL, also install `"sqlseed[postgres]==0.2.5"`.
42
+ is needed to use the app. For PostgreSQL, also install `"sqlseed[postgres]==0.2.6"`.
22
43
  Core 0.2.4 and older lack the shared connection and diagnostic interfaces required by this version.
23
44
 
24
45
  For development, install local Core and Web together from the repository root:
@@ -27,13 +48,13 @@ For development, install local Core and Web together from the repository root:
27
48
  python -m pip install -e . -e ./plugins/sqlseed-web
28
49
  ```
29
50
 
30
- Version 0.2.5 and its source candidates require Core `>=0.2.5.dev0,<0.3` for
51
+ Version 0.2.6 and its source candidates require Core `>=0.2.5.dev0,<0.3` for
31
52
  connection-target parsing and diagnostic redaction. Install matching Core and Web
32
53
  versions; do not disable dependency checks to keep an older Core.
33
54
 
34
55
  ## Interface language
35
56
 
36
- Version 0.2.5 offers **简体中文 / English** in the top bar.
57
+ Version 0.2.6 offers **简体中文 / English** in the top bar.
37
58
  The browser remembers your choice and synchronizes it with other tabs on the same
38
59
  origin. Without a saved choice, the first supported browser language is used,
39
60
  falling back to English. If storage is unavailable, switching still works for the
@@ -65,10 +86,10 @@ install local Core, CLI, AI, and Web together in the same resolution:
65
86
  python -m pip install -e . -e ./plugins/sqlseed-cli -e ./plugins/sqlseed-ai -e ./plugins/sqlseed-web
66
87
  ```
67
88
 
68
- For version 0.2.5, `python -m pip install "sqlseed-web[ai]==0.2.5"` installs
89
+ For version 0.2.6, `python -m pip install "sqlseed-web[ai]==0.2.6"` installs
69
90
  the optional AI component. The page does not fall back to an incompatible older release.
70
91
 
71
- The version 0.2.5 default launcher manages optional packages
92
+ The version 0.2.6 default launcher manages optional packages
72
93
  in supported writable Windows, macOS and Linux virtual environments and restores
73
94
  the service automatically. Externally hosted apps and read-only/system environments
74
95
  can use the workbench but do not offer in-page package changes. Missing components
@@ -4,16 +4,35 @@
4
4
 
5
5
  面向 SQLite 与 PostgreSQL 声明式测试数据生成的本机浏览器工作台。连接数据库、编辑字段规则、预览样例、检查依赖并查看生成结果。Python core 离线运行;AI 建议是可选功能。
6
6
 
7
+ ## 工作台概览
8
+
9
+ ![sqlseed Web 简体中文浅色界面:左侧选表和四表关系图](https://raw.githubusercontent.com/sunbos/sqlseed/992ba0e733d5b41f73e37b0a9d02d573d6e2bb23/docs/assets/screenshots/web-workbench-zh-CN-light.png)
10
+
11
+ 0.2.5 正式界面的实际截图,使用仓库中的虚构 SQLite 订单示例。
12
+ [查看原尺寸高清 PNG](https://raw.githubusercontent.com/sunbos/sqlseed/992ba0e733d5b41f73e37b0a9d02d573d6e2bb23/docs/assets/screenshots/web-workbench-zh-CN-light.png),
13
+ 或[查看深色主题下的只读样例预览](https://raw.githubusercontent.com/sunbos/sqlseed/992ba0e733d5b41f73e37b0a9d02d573d6e2bb23/docs/assets/screenshots/web-workbench-zh-CN-dark.png)。
14
+
15
+ 连接已有数据库 → 选择表和生成数量 → 核对字段规则与依赖 → 预览样例 → 确认生成计划。
16
+
17
+ | 页面 | 可以做什么 |
18
+ | --- | --- |
19
+ | 工作台 | 编辑规则、浏览关系图、只读预览样例,并确认生成。 |
20
+ | 配置管理 | 保存可复用规则、导入导出 YAML、重新打开对应数据库的配置。 |
21
+ | 运行记录 | 查看逐表结果、实际已提交行数和本次使用的配置快照。 |
22
+ | 设置 | 调整生成默认值、浅色/深色外观、可选 AI 设置与组件。 |
23
+
24
+ [订单工作流示例](https://github.com/sunbos/sqlseed/tree/main/examples/order_workflow)提供建表结构、生成规则和操作说明,可用于创建自己的独立演示库。
25
+
7
26
  ## 安装
8
27
 
9
- 本文安装说明对应 0.2.5 版本;发布状态以 [Releases](https://github.com/sunbos/sqlseed/releases) 为准。测试尚未发布的候选版本时,使用下方的源码安装方式。请先创建并激活 Python 3.10+ 虚拟环境:
28
+ 本文安装说明对应 0.2.6 版本;发布状态以 [Releases](https://github.com/sunbos/sqlseed/releases) 为准。测试尚未发布的候选版本时,使用下方的源码安装方式。请先创建并激活 Python 3.10+ 虚拟环境:
10
29
 
11
30
  ```bash
12
- python -m pip install "sqlseed==0.2.5" "sqlseed-web==0.2.5"
31
+ python -m pip install "sqlseed==0.2.6" "sqlseed-web==0.2.6"
13
32
  sqlseed-web
14
33
  ```
15
34
 
16
- 打开 `http://127.0.0.1:8630`。wheel 包含前端,使用时无需 Node 或 npm 构建。PostgreSQL 还需安装 `"sqlseed[postgres]==0.2.5"`。Core 0.2.4 及更早版本缺少本版本所需的共享连接和诊断接口。
35
+ 打开 `http://127.0.0.1:8630`。wheel 包含前端,使用时无需 Node 或 npm 构建。PostgreSQL 还需安装 `"sqlseed[postgres]==0.2.6"`。Core 0.2.4 及更早版本缺少本版本所需的共享连接和诊断接口。
17
36
 
18
37
  开发源码从仓库根同时安装 Core 与 Web:
19
38
 
@@ -21,15 +40,15 @@ sqlseed-web
21
40
  python -m pip install -e . -e ./plugins/sqlseed-web
22
41
  ```
23
42
 
24
- 0.2.5 版本及其源码候选要求 Core `>=0.2.5.dev0,<0.3`,用于连接目标解析与诊断脱敏。请使用匹配的 Core 与 Web 版本,不要关闭依赖检查来保留旧 Core。
43
+ 0.2.6 版本及其源码候选要求 Core `>=0.2.5.dev0,<0.3`,用于连接目标解析与诊断脱敏。请使用匹配的 Core 与 Web 版本,不要关闭依赖检查来保留旧 Core。
25
44
 
26
45
  ## 界面语言
27
46
 
28
- 0.2.5 版本在顶栏提供 **简体中文 / English**。浏览器记住选择,并与同源标签页同步。没有已存偏好时,采用浏览器偏好中第一个支持的语言,无匹配则使用 English;存储不可用时仍能在当前页切换。
47
+ 0.2.6 版本在顶栏提供 **简体中文 / English**。浏览器记住选择,并与同源标签页同步。没有已存偏好时,采用浏览器偏好中第一个支持的语言,无匹配则使用 English;存储不可用时仍能在当前页切换。
29
48
 
30
49
  切换就地更新标签、帮助和受支持的诊断,不刷新页面、不提交表单,也不发数据库或 AI 请求;未保存的修改、焦点和选择保持不变。**数据语言与地区**是独立的生成配置:切换界面语言不改变生成内容、配置名称、表列标识、YAML 或数据库原值。旧记录或第三方诊断可能保留原文,并附当前语言说明。
31
50
 
32
- 语言资源随 wheel 分发,不需要翻译服务。覆盖与新增文案所需验证见 [Web 双语维护](https://sunbos.github.io/sqlseed/development/web-i18n/)。
51
+ 语言资源随 wheel 分发,不需要翻译服务。覆盖与新增文案所需验证见 [Web 双语维护](https://sunbos.github.io/sqlseed/zh-CN/development/web-i18n/)。
33
52
 
34
53
  ## 可选组件
35
54
 
@@ -41,9 +60,9 @@ python -m pip install -e . -e ./plugins/sqlseed-web
41
60
  python -m pip install -e . -e ./plugins/sqlseed-cli -e ./plugins/sqlseed-ai -e ./plugins/sqlseed-web
42
61
  ```
43
62
 
44
- 0.2.5 使用 `python -m pip install "sqlseed-web[ai]==0.2.5"` 安装可选 AI 组件。页面不会回退到不兼容的旧版本。
63
+ 0.2.6 使用 `python -m pip install "sqlseed-web[ai]==0.2.6"` 安装可选 AI 组件。页面不会回退到不兼容的旧版本。
45
64
 
46
- 0.2.5 的默认启动器可在受支持、可写的 Windows、macOS 与 Linux 虚拟环境中管理可选包,并自动恢复服务。外部托管、只读或系统环境仍可使用工作台,但不开放网页包变更。组件缺失会显示原因和恢复入口,不会静默替换配置中的引擎。更新必须审阅兼容 wheel,保持其他已安装组件的版本;Core 与 Web 由环境的包管理工具更新。
65
+ 0.2.6 的默认启动器可在受支持、可写的 Windows、macOS 与 Linux 虚拟环境中管理可选包,并自动恢复服务。外部托管、只读或系统环境仍可使用工作台,但不开放网页包变更。组件缺失会显示原因和恢复入口,不会静默替换配置中的引擎。更新必须审阅兼容 wheel,保持其他已安装组件的版本;Core 与 Web 由环境的包管理工具更新。
47
66
 
48
67
  ## 数据与部署边界
49
68
 
@@ -51,7 +70,7 @@ python -m pip install -e . -e ./plugins/sqlseed-cli -e ./plugins/sqlseed-ai -e .
51
70
 
52
71
  服务面向一个可信的本机用户,没有多用户认证,默认只监听 loopback。不要直接暴露到不可信网络;同源请求检查不能替代认证或数据库权限。
53
72
 
54
- 详见[工作台指南](https://sunbos.github.io/sqlseed/web-workbench/)与[支持边界](https://sunbos.github.io/sqlseed/maintainable-release/)。
73
+ 详见[工作台指南](https://sunbos.github.io/sqlseed/zh-CN/web-workbench/)与[支持边界](https://sunbos.github.io/sqlseed/zh-CN/maintainable-release/)。
55
74
 
56
75
  ## 依赖
57
76
 
@@ -30,6 +30,7 @@
30
30
  - SQLite URI 中解码后的 NUL、原始 TAB/CR/LF、无效 UTF-8 百分号编码也在注册前拒绝:SQLite 字符串截断与 Python URL 清理/替代解码不同,不能把异常编码折叠成另一目标。合法 UTF-8 与经过百分号编码的 TAB/CR/LF 文件名仍按真实路径识别。
31
31
  - URI 文件路径须经平台路径转换;Windows 的 `/C:/...` 与普通 `C:\...` 指向同一文件。百分号只解码一次,文件名中的字面 `%41` 不能被误识别为 `A`;真实文件别名回归覆盖空格、百分号及编码盘符。
32
32
  - 列表、打开和运行只接受当前 canonical `target_key`,不提供或接受旧身份 aliases。旧 URI hash 可能恰好属于另一个真实的 `file:` 前缀文件,不能仅凭当前连接写法推导旧 hash 并自动授权;没有可信身份版本的记录不得通过同 schema 或解析 target_label 猜库迁移。普通路径的旧 key 不变;身份发生变化的旧 URI 配置与运行仍保留可导出,由用户明确导入当前目标创建新配置,历史运行快照不改。历史记录未存原始连接或身份算法版本,旧错 hash 与真实字面 `file:` 路径 hash 的反向碰撞无法可靠区分,这是既有数据的限制,不自动推断或重绑。
33
+ - macOS 的 SQLite 文件身份通过 Darwin libc `realpath(3)` 获取实际拼写,兼容文件系统认可的大小写和 Unicode 别名;不能直接 lower 路径或只凭文字归一化合并不同文件。身份查询不得打开再关闭数据库文件,否则可能释放同进程 SQLite 的 POSIX 锁;原生调用固定 ctypes 签名并使用 Python 持有的 PATH_MAX buffer,失败不采用部分输出。缺失路径不创建文件,其他查验失败不猜测身份;已保存的非规范别名历史不自动重绑,沿用明确导入策略。
33
34
  - Web locale 使用 Faker 风格(`zh_CN`/`en_US`);`SUPPORTED_LOCALES` 与 `MimesisProvider.set_locale` 的映射保持一致。
34
35
 
35
36
  ## 后台任务与终态
@@ -103,6 +104,7 @@
103
104
  ## 可选组件自动管理
104
105
 
105
106
  - `supervisor.py` 在默认启动时持有监听 socket 与管理状态,`managed_worker.py` 分别启动业务/维护 worker,`worker_control.py` 以有界匿名 IPC 传递控制与临时会话。保留原 NDJSON,不代理 HTTP。旧 `--manage-plugins` 仅兼容入口;普通网页无需命令切换或手动重启。
107
+ - Worker 就绪与恢复准入确认是两个步骤。`resume` 确认丢失时可能已有业务请求,必须保留该进程与控制通道,确认自然排空退出后才启动维护 worker;不得覆盖引用或强杀可能已恢复准入的进程。启动失败保留固定阶段、错误码、耗时与退出码,任务输出和 `recovery_error` 不带原始异常/凭据;`/recover` 仅恢复服务和原会话,不重复安装器。启动期限仍为有界的 20 秒,不用扩大期限代替退出/超时诊断。
106
108
  - 维护 worker 业务 `/api/` 一律拒绝,仅保留 health、environment 与 `/api/settings/plugins/*`;HTML 固定标识用于首次导航,API 门禁不能依赖前端,受管维护标识不得永久锁定恢复后的导航。
107
109
  - `plugin_environment.py` 只接受当前解释器与可写独立 virtualenv,解析真实 distribution metadata/Requires-Dist;不使用 import 缓存判断新安装状态。系统/只读/共享系统包/环境外 metadata 不可管理,但保留普通 Web。
108
110
  - `plugin_management.py` 白名单仅 ai/cli/mcp/mimesis。管理请求检查 loopback client/Host;POST 必须同 Origin 及 token。计划绑定五分钟内 metadata 快照,一次领取。新计划可在同一受锁解释器且权限仍满足时重新绑定合法安装器;计划到执行及更新下载后的环境变化仍须拒绝,不能将短时安装器探测结果固定为进程生命周期身份。Core/Web/Faker/Base 不接受操作,不自动卸载依赖。`supervised_plugins.py` 仅在新业务就绪后发布任务终态,恢复失败保留页面与只恢复服务的重试入口。
@@ -28,6 +28,33 @@ if TYPE_CHECKING:
28
28
 
29
29
  from sqlseed_web.runtime_lifecycle import RuntimeGate
30
30
 
31
+ _WORKER_STARTUP_FAILED = "backend.supervisor.worker_startup_failed"
32
+
33
+
34
+ class WorkerLifecycleError(RuntimeError):
35
+ """Only fixed lifecycle facts may cross the public recovery boundary."""
36
+
37
+ def __init__(self, code: str, *, mode: str, phase: str, elapsed_ms: int, exit_code: int | None) -> None:
38
+ """Build a localized error from fixed lifecycle facts without private exception text."""
39
+ messages = {
40
+ "worker_startup_timeout": tr("backend.supervisor.worker_startup_timeout"),
41
+ "worker_exited_before_ready": tr("backend.supervisor.worker_exited_before_ready"),
42
+ "worker_startup_failed": tr(_WORKER_STARTUP_FAILED),
43
+ "worker_resume_failed": tr("backend.supervisor.worker_resume_failed"),
44
+ "worker_shutdown_timeout": tr("backend.supervisor.worker_shutdown_timeout"),
45
+ "worker_stop_pending": tr("backend.supervisor.worker_stop_pending"),
46
+ }
47
+ message = messages[code]
48
+ super().__init__(message)
49
+ self.detail: dict[str, Any] = {
50
+ "code": code,
51
+ "message": message,
52
+ "worker_mode": mode,
53
+ "phase": phase,
54
+ "elapsed_ms": elapsed_ms,
55
+ "exit_code": exit_code,
56
+ }
57
+
31
58
 
32
59
  class RemotePluginManager:
33
60
  """The HTTP worker cannot execute package operations itself."""
@@ -145,6 +172,33 @@ def _serve_worker(server: uvicorn.Server, listener: socket.socket) -> None:
145
172
  asyncio.set_event_loop(None)
146
173
 
147
174
 
175
+ def _restore_worker_session(mode: str, session: dict[str, Any]) -> dict[str, Any]:
176
+ """Restore business connections only; maintenance workers must not open databases."""
177
+ if mode != "business":
178
+ return {}
179
+ from sqlseed_web.runtime_session import restore_session
180
+
181
+ if session:
182
+ return restore_session(session)
183
+ return {"restored_connections": 0, "failed_connections": [], "ai_session_restored": True}
184
+
185
+
186
+ def _wait_for_http_start(server: uvicorn.Server, thread: threading.Thread) -> None:
187
+ """Wait for HTTP readiness or report a safe error if its serving thread exits first."""
188
+ while thread.is_alive() and not server.started:
189
+ time.sleep(0.01)
190
+ if not server.started:
191
+ raise RuntimeError(tr(_WORKER_STARTUP_FAILED))
192
+
193
+
194
+ def _report_startup_failure(channel: ControlChannel, mode: str, stage: str) -> None:
195
+ """Send only the failed stage, tolerating a parent control channel that has already closed."""
196
+ try:
197
+ channel.call("worker_failed", {"mode": mode, "phase": stage})
198
+ except (OSError, RuntimeError):
199
+ pass
200
+
201
+
148
202
  def run_worker(
149
203
  listener: socket.socket,
150
204
  connection: ControlTransport,
@@ -163,7 +217,6 @@ def run_worker(
163
217
  signal.signal(signal.SIGTERM, signal.SIG_IGN)
164
218
  channel = ControlChannel(connection)
165
219
  manager = RemotePluginManager(channel, token)
166
- result: dict[str, Any] = {}
167
220
  server: uvicorn.Server | None = None
168
221
  thread: threading.Thread | None = None
169
222
  lock_fd = lock_descriptor.detach() if lock_descriptor is not None else None
@@ -172,20 +225,14 @@ def run_worker(
172
225
  return _worker_control(method, mode, server, runtime_gate)
173
226
 
174
227
  channel.start(control)
228
+ stage = "session"
229
+ announced_ready = False
175
230
  try:
231
+ channel.call("worker_starting", {"mode": mode, "phase": stage})
176
232
  runtime_gate.pause_if_idle()
177
- if mode == "business":
178
- from sqlseed_web.runtime_session import restore_session
179
-
180
- result = (
181
- restore_session(session)
182
- if session
183
- else {
184
- "restored_connections": 0,
185
- "failed_connections": [],
186
- "ai_session_restored": True,
187
- }
188
- )
233
+ result = _restore_worker_session(mode, session)
234
+ stage = "application"
235
+ channel.call("worker_starting", {"mode": mode, "phase": stage})
189
236
  app = create_app(manage_plugins=mode == "maintenance", management_service=manager, supervised_worker=True)
190
237
  config = uvicorn.Config(
191
238
  app, log_level="warning", access_log=False, lifespan="on", timeout_graceful_shutdown=None
@@ -194,14 +241,20 @@ def run_worker(
194
241
  thread = threading.Thread(
195
242
  target=_serve_worker, args=(server, listener), daemon=False, name="sqlseed-http-worker"
196
243
  )
244
+ stage = "http"
245
+ channel.call("worker_starting", {"mode": mode, "phase": stage})
197
246
  thread.start()
198
- while thread.is_alive() and not server.started:
199
- time.sleep(0.01)
200
- if server.started:
201
- channel.call("worker_ready", {"mode": mode, "restoration": result})
247
+ _wait_for_http_start(server, thread)
248
+ channel.call("worker_ready", {"mode": mode, "restoration": result})
249
+ announced_ready = True
202
250
  while thread.is_alive():
203
251
  if channel.wait_closed(0.1):
204
252
  break
253
+ except (HTTPException, ImportError, OSError, RuntimeError, TypeError, ValueError):
254
+ if not announced_ready:
255
+ _report_startup_failure(channel, mode, stage)
256
+ # Import/ASGI failures may contain credentials or driver parameters.
257
+ raise RuntimeError(tr(_WORKER_STARTUP_FAILED)) from None
205
258
  finally:
206
259
  _drain_worker_runtime(mode, runtime_gate)
207
260
  if server is not None:
@@ -2,7 +2,12 @@
2
2
 
3
3
  from __future__ import annotations
4
4
 
5
+ import ctypes
6
+ import errno
7
+ import os
8
+ import sys
5
9
  from dataclasses import dataclass
10
+ from functools import cache
6
11
  from pathlib import Path
7
12
  from typing import Literal
8
13
  from urllib.parse import parse_qs, quote, unquote, urlencode, urlsplit
@@ -15,6 +20,36 @@ from sqlseed.database._connection_url import connection_url
15
20
  from sqlseed_web.messages import message as tr
16
21
 
17
22
 
23
+ @cache
24
+ def _macos_libc() -> ctypes.CDLL:
25
+ """Bind Darwin realpath once with its native pointer signature."""
26
+ library = ctypes.CDLL(None, use_errno=True)
27
+ library.realpath.argtypes = [ctypes.c_char_p, ctypes.POINTER(ctypes.c_char)]
28
+ library.realpath.restype = ctypes.c_void_p
29
+ return library
30
+
31
+
32
+ def _canonical_file_path(filename: str) -> str:
33
+ """Resolve macOS filesystem spellings without folding distinct filenames."""
34
+ path = Path(filename).resolve()
35
+ if sys.platform != "darwin":
36
+ return str(path)
37
+ # Unlike Python's realpath, Darwin libc reads each component's actual
38
+ # filesystem name. It neither scans directories nor opens the database;
39
+ # closing an extra database descriptor would release active POSIX locks.
40
+ # Darwin sys/syslimits.h defines PATH_MAX=1024. Passing our own buffer
41
+ # avoids libc-allocated memory and retains ownership on every error path.
42
+ buffer = ctypes.create_string_buffer(1024)
43
+ if _macos_libc().realpath(os.fsencode(path), buffer):
44
+ return os.fsdecode(buffer.value)
45
+ if (error := ctypes.get_errno()) in {errno.ENOENT, errno.ENOTDIR}:
46
+ # Identity lookup must not create a missing database; existing callers
47
+ # retain their own create/no-create policy when opening it later.
48
+ return str(path)
49
+ # realpath's partial output on failure is not a valid target identity.
50
+ raise OSError(error, os.strerror(error), str(path))
51
+
52
+
18
53
  @dataclass(frozen=True)
19
54
  class SQLiteTarget:
20
55
  """A file, a named shared memory database, or one private connection."""
@@ -86,7 +121,7 @@ def sqlite_target(target: str, conn_id: str) -> SQLiteTarget | None:
86
121
  # Re-encode the validated text so literal percent sequences are not
87
122
  # decoded twice by url2pathname; keep drive colons visible to it.
88
123
  filename = url2pathname(quote(filename, safe="/:"))
89
- return SQLiteTarget("sqlite", str(Path(filename).resolve()))
124
+ return SQLiteTarget("sqlite", _canonical_file_path(filename))
90
125
 
91
126
 
92
127
  def existing_sqlite_connection_target(target: str, conn_id: str) -> str:
@@ -731,6 +731,34 @@
731
731
  "业务进程意外退出,原有连接与会话密钥需要重新配置。",
732
732
  "The application process stopped unexpectedly. Reconfigure connections and session keys."
733
733
  ],
734
+ "backend.supervisor.worker_startup_timeout": [
735
+ "应用进程未在启动期限内就绪,请重试恢复;不会重复安装组件。",
736
+ "The application process did not become ready before its startup deadline. Retry recovery; the component will not be installed again."
737
+ ],
738
+ "backend.supervisor.worker_exited_before_ready": [
739
+ "应用进程在就绪前退出,请检查组件环境后重试恢复。",
740
+ "The application process exited before becoming ready. Check the component environment and retry recovery."
741
+ ],
742
+ "backend.supervisor.worker_startup_failed": [
743
+ "应用进程初始化失败,请检查组件环境后重试恢复。",
744
+ "Application process initialization failed. Check the component environment and retry recovery."
745
+ ],
746
+ "backend.supervisor.worker_resume_failed": [
747
+ "未能确认应用进程已恢复服务,将先等待该进程安全退出,再恢复工作台。",
748
+ "The application process did not acknowledge service resumption. Wait for that process to exit safely before restoring the workbench."
749
+ ],
750
+ "backend.supervisor.worker_shutdown_timeout": [
751
+ "原应用进程尚未安全退出,已保留进程与环境锁;请稍后重试恢复。",
752
+ "The previous application process has not exited safely. Its ownership and environment lock are retained; retry recovery shortly."
753
+ ],
754
+ "backend.supervisor.worker_stop_pending": [
755
+ "原应用进程尚未完成清理,不能启动替代进程;请稍后重试恢复。",
756
+ "The previous application process has not finished cleanup. A replacement cannot start yet; retry recovery shortly."
757
+ ],
758
+ "backend.supervised_plugins.service_restore_failed": [
759
+ "服务恢复未完成,请重试恢复;组件操作不会重复执行。",
760
+ "Service recovery did not complete. Retry recovery; the component operation will not run again."
761
+ ],
734
762
  "backend.supervisor.another_web_service_is_using_this_python": [
735
763
  "此 Python 环境正被另一个 Web 服务使用,无法启动受管服务。",
736
764
  "Another Web service is using this Python environment. Cannot start the managed service."
@@ -67,9 +67,9 @@ const readingTable = table(['#', '字段', '规则', '示例'], [
67
67
  readingTable.classList.add('wb-preview-data');
68
68
  root.append(section('foundation', '材质与文字', '透明度服从信息层级。功能层轻盈,数据与代码保持稳定阅读。', 'fields',
69
69
  h('div', { class: 'ds-grid ds-grid-three' },
70
- surface('wb-config-context', '控制层', '用于配置工具栏与导航,柔和区分背景。', '--glass'),
71
- surface('wb-content', '阅读层', '用于字段、记录和配置正文,减少背景干扰。', '--paper'),
72
- surface('drawer-help', '内嵌说明', '用于规则说明与样例,边缘保持自然。', '--glass')),
70
+ surface('wb-config-context', '控制层', '导航与临时操作使用轻透表面,通过边缘区分层级。', '--surface-control'),
71
+ surface('wb-content', '阅读层', '字段、记录和配置正文使用稳定底色,不模糊其后的内容。', '--surface-data'),
72
+ surface('drawer-help', '内嵌说明', '规则说明与写入事实使用安静的底板,不在浮层中叠加玻璃。', '--wash')),
73
73
  h('div', { class: 'ds-fonts' }, h('div', { class: 'table-title' }, h('h2', {}, 'users · 用户基础信息')),
74
74
  h('span', {}, 'orders · 每一行,都有依据。'), h('code', { class: 'mono' }, 'user_id INTEGER'),
75
75
  h('span', {}, '1,024 行 · 2026-09-26')),
@@ -125,6 +125,11 @@ const countInput = h('input', { type: 'text', inputmode: 'numeric', value: '0',
125
125
  const countField = field('生成数量 · 错误恢复示例', countInput);
126
126
  countField.append(countError);
127
127
  const stageSample = h('ol', {class:'wb-guide-stages', 'aria-label':'生成流程样式示例'});
128
+ const pathShortcutSample = button('', () => {
129
+ const selected = pathShortcutSample.getAttribute('aria-pressed') !== 'true';
130
+ pathShortcutSample.setAttribute('aria-pressed', String(selected));
131
+ actionStatus.textContent = selected ? '依赖路径入口已选中;此样例未修改配置。' : '依赖路径入口恢复普通状态;此样例未修改配置。';
132
+ }, {glyph:'relations', plain:true, class:'table-graph-shortcut', 'aria-label':'查看依赖路径样例', title:'查看依赖路径样例', 'aria-pressed':'false'});
128
133
  let stageIndicator;
129
134
  for (const [index, [label, hint]] of [['设定规则','选择表与字段'],['预览样例','只读查看结果'],['确认写入','核对生成计划']].entries()) {
130
135
  const stage = button('', () => {
@@ -143,8 +148,7 @@ root.append(section('controls', '基础控件', '悬停、键盘焦点与选中
143
148
  actionStatus,
144
149
  h('h3',{},'关系图入口 · 节点与分支'),
145
150
  h('div', {class:'ds-row'},
146
- button('', () => { actionStatus.textContent = '依赖路径入口样例;正式工作台会定位当前表的关系图。'; },
147
- {glyph:'relations', plain:true, class:'table-graph-shortcut', 'aria-label':'查看依赖路径样例', title:'查看依赖路径样例'}),
151
+ pathShortcutSample,
148
152
  button('查看关系图', () => { actionStatus.textContent = '带文字的关系图入口样例,没有修改配置。'; }, {glyph:'relations',small:true})),
149
153
  h('h3',{},'生成流程 · 分段导航'), stageSample,
150
154
  h('h3',{},'连接恢复 · 主次操作'),
@@ -164,7 +168,7 @@ root.append(section('controls', '基础控件', '悬停、键盘焦点与选中
164
168
  notes('Tab 逐项移动焦点,Space 切换复选框;焦点环不等同于已选状态。',
165
169
  '鼠标悬停呈现柔和阴影,按钮不移动;已选底色仍然保留,键盘焦点继续有清晰外圈。',
166
170
  '绿色主按钮使用同色相渐变、低反光内缘与柔和外阴影表达厚度;按下时回落,不出现白色亮顶线。',
167
- '关系入口使用三个圆角节点和正交分支;检查小尺寸轮廓、明暗描边与键盘提示,不依赖图标独自解释功能。',
171
+ '关系入口使用居中的三个圆角节点和正交分支;点击样例切换选中状态。桌面触发区为 32×32px,窄屏及触控为 44×44px;检查明暗、悬停和键盘焦点,图标与触发区保持同心。',
168
172
  '生成流程共用底槽,选中底板短暂滑动,编号和文字保持原位;窄屏换行、初载和尺寸变化直接定位。',
169
173
  '快速来回切换时底板从当前位置转向;系统选择减少动态效果时立即切换。复选框和单选框只让标记短暂浮现,输入框不会位移。',
170
174
  '连接恢复按钮居中并保持间距,窄屏自然换行;主操作和次操作使用正式按钮样式。',
@@ -372,7 +372,7 @@ export function createDropdown({
372
372
  }
373
373
  function reposition(event) {
374
374
  // 列表内部滚动只更新方向提示,不重新测量定位或改动其滚动位置。
375
- if (event?.target && popup.contains(event.target)) {
375
+ if (event?.type === 'scroll' && event.target && popup.contains(event.target)) {
376
376
  return;
377
377
  }
378
378
  // 属性面板被 render() 整体重绘时(切列 / 切生成器 / AI 回填),旧的 dropdown
@@ -1,4 +1,4 @@
1
- import {tr, formatNumber, setText, setAttr, UserFacingError, errorText, serverText} from './i18n.js';
1
+ import {tr, formatNumber, setText, setAttr, UserFacingError, errorText} from './i18n.js';
2
2
  import './i18n/messages/components.js';
3
3
  import {h, api} from './api.js';
4
4
  import {button} from './workbench/ui.js';
@@ -70,7 +70,7 @@ export function createGenerationDefaultsControl() {
70
70
  try {
71
71
  const [languages, providers] = await Promise.all([api('/api/meta/locales', {signal: controller.signal}), api('/api/meta/providers', {signal: controller.signal})]);
72
72
  if (destroyed) return;
73
- localeOptions = languages.locales.map(item => ({value: item.code, label: serverText(item, 'label')}));
73
+ localeOptions = languages.locales.map(item => ({value: item.code, label: item.label}));
74
74
  providerFacts = providers.statuses || {};
75
75
  // Keep unavailable stored choices visible; never silently switch their meaning.
76
76
  const value = locale.get();
@@ -10,7 +10,7 @@
10
10
  ],
11
11
  "configs": [
12
12
  "配置管理",
13
- "Configurations"
13
+ "Configs"
14
14
  ],
15
15
  "runs": [
16
16
  "运行记录",
@@ -1,5 +1,19 @@
1
1
  {
2
2
  "workbench": {
3
+ "scope.viewing": ["当前查看:{table}", "Viewing: {table}"],
4
+ "scope.noTable": ["暂无表", "No table"],
5
+ "scope.selectedCount": ["已选 {count} 张表用于生成", {"one":"{count} table selected for generation", "other":"{count} tables selected for generation"}],
6
+ "guide.currentStage": ["{stage}/3 · {title}", "{stage}/3 · {title}"],
7
+ "guide.rulesShort": ["规则", "Rules"],
8
+ "guide.previewShort": ["样例", "Preview"],
9
+ "guide.confirmShort": ["确认", "Confirm"],
10
+ "execution.status.ready": ["已核对,确认后将写入数据库。", "Reviewed. Confirm to write to the database."],
11
+ "execution.status.checking": ["正在核对写入方案,请稍候。", "Checking the write plan. Please wait."],
12
+ "execution.status.busy": ["正在提交写入,请勿重复操作。", "Submitting the write. Please wait."],
13
+ "execution.status.blocked": ["暂不能写入,请查看原因并调整。", "Writing is blocked. Review the reasons and adjust."],
14
+ "execution.status.failure": ["未能完成,请查看原因后重试。", "The request failed. Review the reasons before retrying."],
15
+ "execution.viewReasons": ["查看原因", "View reasons"],
16
+ "execution.diagnostics": ["详细诊断", "Detailed diagnostics"],
3
17
  "unsupported.title": ["当前工作台不支持此生成范围", "This generation scope is not supported"],
4
18
  "unsupported.body": [
5
19
  "所选范围包含当前不支持的跨表循环:{tables}。这不是行数或生成器参数错误。具体原因见下方;SQLite 追加仅在循环内每条单列外键已有可用父键时受支持,缺少来源时全选或原样重试无法解除限制。",