ApiLogicServer 15.0.47__py3-none-any.whl → 15.0.54__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 (123) hide show
  1. api_logic_server_cli/api_logic_server.py +18 -5
  2. api_logic_server_cli/api_logic_server_info.yaml +3 -3
  3. api_logic_server_cli/cli.py +20 -16
  4. api_logic_server_cli/create_from_model/api_logic_server_utils.py +10 -1
  5. api_logic_server_cli/manager.py +24 -13
  6. api_logic_server_cli/prototypes/base/.github/.copilot-instructions.md +39 -3
  7. api_logic_server_cli/prototypes/base/config/config.py +15 -0
  8. api_logic_server_cli/prototypes/base/database/alembic/alembic_run.py +98 -0
  9. api_logic_server_cli/prototypes/base/database/alembic/readme_alembic.md +36 -0
  10. api_logic_server_cli/prototypes/base/docs/training/admin_app_1_context.prompt.md +40 -0
  11. api_logic_server_cli/prototypes/base/integration/mcp/mcp_client_executor.py +2 -2
  12. api_logic_server_cli/prototypes/base/venv_setup/requirements-no-cli.txt +5 -4
  13. api_logic_server_cli/prototypes/basic_demo/_config.yml +8 -0
  14. api_logic_server_cli/prototypes/basic_demo/_layouts/redirect.html +15 -0
  15. api_logic_server_cli/prototypes/basic_demo/docs/system-creation-vibe.md +161 -0
  16. api_logic_server_cli/prototypes/basic_demo/logic/declarative-vs-procedural-comparison.html +110 -0
  17. api_logic_server_cli/prototypes/basic_demo/logic/procedural/declarative-vs-procedural-comparison.md +295 -0
  18. api_logic_server_cli/prototypes/manager/.vscode/settings.json +1 -1
  19. api_logic_server_cli/prototypes/manager/{run_sample.sh → samples/docker_samples/run_sample_docker.sh} +4 -4
  20. api_logic_server_cli/prototypes/manager/samples/docker_samples/run_web_genai.sh +5 -0
  21. api_logic_server_cli/prototypes/manager/samples/prompts/add_email.prompt +8 -0
  22. api_logic_server_cli/prototypes/manager/samples/prompts/elections.prompt +3 -0
  23. api_logic_server_cli/prototypes/manager/samples/prompts/emp_dept.prompt +4 -0
  24. api_logic_server_cli/prototypes/manager/samples/prompts/genai_demo.prompt +13 -0
  25. api_logic_server_cli/prototypes/manager/samples/readme_samples.md +25 -11
  26. api_logic_server_cli/prototypes/manager/system/app_model_editor/venv_setup/requirements-no-cli.txt +5 -4
  27. api_logic_server_cli/prototypes/manager/system/genai/app_templates/app_learning/Admin-App-Resource-Learning-Prompt.md +1 -1
  28. api_logic_server_cli/prototypes/manager/system/genai/app_templates/react-admin-template/package.json +1 -0
  29. api_logic_server_cli/prototypes/manager/system/genai/examples/genai_demo/genai_demo_docs_logic/venv_setup/requirements-no-cli.txt +5 -4
  30. api_logic_server_cli/prototypes/manager/system/install-ApiLogicServer-dev/install-ApiLogicServer-dev.ps1 +7 -3
  31. api_logic_server_cli/prototypes/ont_app/ontimize_seed/package.json +2 -2
  32. api_logic_server_cli/sqlacodegen_wrapper/sqlacodegen/sqlacodegen/codegen.py +4 -2
  33. api_logic_server_cli/sqlacodegen_wrapper/sqlacodegen/sqlacodegen/main.py +25 -5
  34. api_logic_server_cli/sqlacodegen_wrapper/sqlacodegen_wrapper.py +30 -10
  35. {apilogicserver-15.0.47.dist-info → apilogicserver-15.0.54.dist-info}/METADATA +6 -5
  36. {apilogicserver-15.0.47.dist-info → apilogicserver-15.0.54.dist-info}/RECORD +40 -111
  37. api_logic_server_cli/create_from_model/__pycache__/__init__.cpython-312.pyc +0 -0
  38. api_logic_server_cli/create_from_model/__pycache__/api_expose_api_models_creator.cpython-312.pyc +0 -0
  39. api_logic_server_cli/create_from_model/__pycache__/api_logic_server_utils.cpython-312.pyc +0 -0
  40. api_logic_server_cli/create_from_model/__pycache__/create_db_from_model.cpython-312.pyc +0 -0
  41. api_logic_server_cli/create_from_model/__pycache__/dbml.cpython-312.pyc +0 -0
  42. api_logic_server_cli/create_from_model/__pycache__/meta_model.cpython-312.pyc +0 -0
  43. api_logic_server_cli/create_from_model/__pycache__/model_creation_services.cpython-312.pyc +0 -0
  44. api_logic_server_cli/create_from_model/__pycache__/ont_build.cpython-312.pyc +0 -0
  45. api_logic_server_cli/create_from_model/__pycache__/ont_create.cpython-312.pyc +0 -0
  46. api_logic_server_cli/create_from_model/__pycache__/ui_admin_creator.cpython-312.pyc +0 -0
  47. api_logic_server_cli/create_from_model/__pycache__/uri_info.cpython-312.pyc +0 -0
  48. api_logic_server_cli/prototypes/base/.devcontainer-option/.copilot-instructions.md +0 -178
  49. api_logic_server_cli/prototypes/base/database/alembic/readme.md +0 -18
  50. api_logic_server_cli/prototypes/base/database/system/SAFRSBaseX.pyZ +0 -73
  51. api_logic_server_cli/prototypes/basic_demo/customizations/database/system/SAFRSBaseX.py +0 -139
  52. api_logic_server_cli/prototypes/manager/run_web_genai.sh +0 -6
  53. api_logic_server_cli/prototypes/manager/system/genai/examples/genai_demo/genai_demo_docs_logic/__pycache__/api_logic_server_run.cpython-312.pyc +0 -0
  54. api_logic_server_cli/prototypes/manager/system/genai/examples/genai_demo/genai_demo_docs_logic/api/__pycache__/__init__.cpython-312.pyc +0 -0
  55. api_logic_server_cli/prototypes/manager/system/genai/examples/genai_demo/genai_demo_docs_logic/api/__pycache__/customize_api.cpython-312.pyc +0 -0
  56. api_logic_server_cli/prototypes/manager/system/genai/examples/genai_demo/genai_demo_docs_logic/api/__pycache__/expose_api_models.cpython-312.pyc +0 -0
  57. api_logic_server_cli/prototypes/manager/system/genai/examples/genai_demo/genai_demo_docs_logic/api/__pycache__/json_encoder.cpython-312.pyc +0 -0
  58. api_logic_server_cli/prototypes/manager/system/genai/examples/genai_demo/genai_demo_docs_logic/api/api_discovery/__pycache__/auto_discovery.cpython-312.pyc +0 -0
  59. api_logic_server_cli/prototypes/manager/system/genai/examples/genai_demo/genai_demo_docs_logic/api/api_discovery/__pycache__/new_service.cpython-312.pyc +0 -0
  60. api_logic_server_cli/prototypes/manager/system/genai/examples/genai_demo/genai_demo_docs_logic/api/api_discovery/__pycache__/newer_service.cpython-312.pyc +0 -0
  61. api_logic_server_cli/prototypes/manager/system/genai/examples/genai_demo/genai_demo_docs_logic/api/api_discovery/__pycache__/ontimize_api.cpython-312.pyc +0 -0
  62. api_logic_server_cli/prototypes/manager/system/genai/examples/genai_demo/genai_demo_docs_logic/api/api_discovery/__pycache__/system.cpython-312.pyc +0 -0
  63. api_logic_server_cli/prototypes/manager/system/genai/examples/genai_demo/genai_demo_docs_logic/api/system/__pycache__/api_utils.cpython-312.pyc +0 -0
  64. api_logic_server_cli/prototypes/manager/system/genai/examples/genai_demo/genai_demo_docs_logic/api/system/__pycache__/custom_endpoint.cpython-312.pyc +0 -0
  65. api_logic_server_cli/prototypes/manager/system/genai/examples/genai_demo/genai_demo_docs_logic/api/system/__pycache__/expression_parser.cpython-312.pyc +0 -0
  66. api_logic_server_cli/prototypes/manager/system/genai/examples/genai_demo/genai_demo_docs_logic/api/system/__pycache__/gen_csv_report.cpython-312.pyc +0 -0
  67. api_logic_server_cli/prototypes/manager/system/genai/examples/genai_demo/genai_demo_docs_logic/api/system/__pycache__/gen_pdf_report.cpython-312.pyc +0 -0
  68. api_logic_server_cli/prototypes/manager/system/genai/examples/genai_demo/genai_demo_docs_logic/api/system/opt_locking/__pycache__/opt_locking.cpython-312.pyc +0 -0
  69. api_logic_server_cli/prototypes/manager/system/genai/examples/genai_demo/genai_demo_docs_logic/config/__pycache__/__init__.cpython-312.pyc +0 -0
  70. api_logic_server_cli/prototypes/manager/system/genai/examples/genai_demo/genai_demo_docs_logic/config/__pycache__/activate_logicbank.cpython-312.pyc +0 -0
  71. api_logic_server_cli/prototypes/manager/system/genai/examples/genai_demo/genai_demo_docs_logic/config/__pycache__/config.cpython-312.pyc +0 -0
  72. api_logic_server_cli/prototypes/manager/system/genai/examples/genai_demo/genai_demo_docs_logic/config/__pycache__/server_setup.cpython-312.pyc +0 -0
  73. api_logic_server_cli/prototypes/manager/system/genai/examples/genai_demo/genai_demo_docs_logic/database/__pycache__/__init__.cpython-312.pyc +0 -0
  74. api_logic_server_cli/prototypes/manager/system/genai/examples/genai_demo/genai_demo_docs_logic/database/__pycache__/bind_dbs.cpython-312.pyc +0 -0
  75. api_logic_server_cli/prototypes/manager/system/genai/examples/genai_demo/genai_demo_docs_logic/database/__pycache__/customize_models.cpython-312.pyc +0 -0
  76. api_logic_server_cli/prototypes/manager/system/genai/examples/genai_demo/genai_demo_docs_logic/database/__pycache__/models.cpython-312.pyc +0 -0
  77. api_logic_server_cli/prototypes/manager/system/genai/examples/genai_demo/genai_demo_docs_logic/database/alembic/__pycache__/env.cpython-312.pyc +0 -0
  78. api_logic_server_cli/prototypes/manager/system/genai/examples/genai_demo/genai_demo_docs_logic/database/database_discovery/__pycache__/authentication_models.cpython-312.pyc +0 -0
  79. api_logic_server_cli/prototypes/manager/system/genai/examples/genai_demo/genai_demo_docs_logic/database/database_discovery/__pycache__/auto_discovery.cpython-312.pyc +0 -0
  80. api_logic_server_cli/prototypes/manager/system/genai/examples/genai_demo/genai_demo_docs_logic/database/db_debug/__pycache__/db_debug.cpython-312.pyc +0 -0
  81. api_logic_server_cli/prototypes/manager/system/genai/examples/genai_demo/genai_demo_docs_logic/database/system/__pycache__/SAFRSBaseX.cpython-312.pyc +0 -0
  82. api_logic_server_cli/prototypes/manager/system/genai/examples/genai_demo/genai_demo_docs_logic/database/test_data/__pycache__/alp_init.cpython-312.pyc +0 -0
  83. api_logic_server_cli/prototypes/manager/system/genai/examples/genai_demo/genai_demo_docs_logic/database/test_data/__pycache__/response2code.cpython-312.pyc +0 -0
  84. api_logic_server_cli/prototypes/manager/system/genai/examples/genai_demo/genai_demo_docs_logic/database/test_data/__pycache__/test_data_preamble.cpython-312.pyc +0 -0
  85. api_logic_server_cli/prototypes/manager/system/genai/examples/genai_demo/genai_demo_docs_logic/devops/keycloak/unused/__pycache__/auth_provider.cpython-312.pyc +0 -0
  86. api_logic_server_cli/prototypes/manager/system/genai/examples/genai_demo/genai_demo_docs_logic/devops/python-anywhere/__pycache__/python_anywhere_wsgi.cpython-312.pyc +0 -0
  87. api_logic_server_cli/prototypes/manager/system/genai/examples/genai_demo/genai_demo_docs_logic/integration/kafka/__pycache__/kafka_consumer.cpython-312.pyc +0 -0
  88. api_logic_server_cli/prototypes/manager/system/genai/examples/genai_demo/genai_demo_docs_logic/integration/kafka/__pycache__/kafka_producer.cpython-312.pyc +0 -0
  89. api_logic_server_cli/prototypes/manager/system/genai/examples/genai_demo/genai_demo_docs_logic/integration/n8n/__pycache__/n8n_producer.cpython-312.pyc +0 -0
  90. api_logic_server_cli/prototypes/manager/system/genai/examples/genai_demo/genai_demo_docs_logic/integration/system/__pycache__/FlaskKafka.cpython-312.pyc +0 -0
  91. api_logic_server_cli/prototypes/manager/system/genai/examples/genai_demo/genai_demo_docs_logic/integration/system/__pycache__/RowDictMapper.cpython-312.pyc +0 -0
  92. api_logic_server_cli/prototypes/manager/system/genai/examples/genai_demo/genai_demo_docs_logic/logic/__pycache__/declare_logic.cpython-312.pyc +0 -0
  93. api_logic_server_cli/prototypes/manager/system/genai/examples/genai_demo/genai_demo_docs_logic/logic/__pycache__/load_verify_rules.cpython-312.pyc +0 -0
  94. api_logic_server_cli/prototypes/manager/system/genai/examples/genai_demo/genai_demo_docs_logic/logic/logic_discovery/__pycache__/auto_discovery.cpython-312.pyc +0 -0
  95. api_logic_server_cli/prototypes/manager/system/genai/examples/genai_demo/genai_demo_docs_logic/security/__pycache__/__init__.cpython-312.pyc +0 -0
  96. api_logic_server_cli/prototypes/manager/system/genai/examples/genai_demo/genai_demo_docs_logic/security/__pycache__/declare_security.cpython-312.pyc +0 -0
  97. api_logic_server_cli/prototypes/manager/system/genai/examples/genai_demo/genai_demo_docs_logic/security/authentication_provider/__pycache__/__init__.cpython-312.pyc +0 -0
  98. api_logic_server_cli/prototypes/manager/system/genai/examples/genai_demo/genai_demo_docs_logic/security/authentication_provider/__pycache__/abstract_authentication_provider.cpython-312.pyc +0 -0
  99. api_logic_server_cli/prototypes/manager/system/genai/examples/genai_demo/genai_demo_docs_logic/security/authentication_provider/keycloak/__pycache__/auth_provider.cpython-312.pyc +0 -0
  100. api_logic_server_cli/prototypes/manager/system/genai/examples/genai_demo/genai_demo_docs_logic/security/authentication_provider/memory/__pycache__/auth_provider.cpython-312.pyc +0 -0
  101. api_logic_server_cli/prototypes/manager/system/genai/examples/genai_demo/genai_demo_docs_logic/security/authentication_provider/memory/__pycache__/auth_provider_no_swagger.cpython-312.pyc +0 -0
  102. api_logic_server_cli/prototypes/manager/system/genai/examples/genai_demo/genai_demo_docs_logic/security/authentication_provider/sql/__pycache__/auth_provider.cpython-312.pyc +0 -0
  103. api_logic_server_cli/prototypes/manager/system/genai/examples/genai_demo/genai_demo_docs_logic/security/system/__pycache__/authentication.cpython-312.pyc +0 -0
  104. api_logic_server_cli/prototypes/manager/system/genai/examples/genai_demo/genai_demo_docs_logic/security/system/__pycache__/authorization.cpython-312.pyc +0 -0
  105. api_logic_server_cli/prototypes/manager/system/genai/examples/genai_demo/genai_demo_docs_logic/test/__pycache__/__init__.cpython-312.pyc +0 -0
  106. api_logic_server_cli/prototypes/manager/system/genai/examples/genai_demo/genai_demo_docs_logic/test/api_logic_server_behave/__pycache__/__init__.cpython-312.pyc +0 -0
  107. api_logic_server_cli/prototypes/manager/system/genai/examples/genai_demo/genai_demo_docs_logic/test/api_logic_server_behave/__pycache__/behave_logic_report.cpython-312.pyc +0 -0
  108. api_logic_server_cli/prototypes/manager/system/genai/examples/genai_demo/genai_demo_docs_logic/test/api_logic_server_behave/__pycache__/behave_run.cpython-312.pyc +0 -0
  109. api_logic_server_cli/prototypes/manager/system/genai/examples/genai_demo/genai_demo_docs_logic/test/api_logic_server_behave/features/steps/__pycache__/about.cpython-312.pyc +0 -0
  110. api_logic_server_cli/prototypes/manager/system/genai/examples/genai_demo/genai_demo_docs_logic/test/api_logic_server_behave/features/steps/__pycache__/test_utils.cpython-312.pyc +0 -0
  111. api_logic_server_cli/prototypes/manager/system/genai/examples/genai_demo/genai_demo_docs_logic/test/basic/__pycache__/server_test.cpython-312.pyc +0 -0
  112. api_logic_server_cli/prototypes/manager/system/genai/examples/genai_demo/genai_demo_docs_logic/ui/__pycache__/__init__.cpython-312.pyc +0 -0
  113. api_logic_server_cli/prototypes/manager/system/genai/examples/genai_demo/genai_demo_docs_logic/ui/admin/__pycache__/admin_loader.cpython-312.pyc +0 -0
  114. api_logic_server_cli/prototypes/manager/system/genai/examples/genai_demo/genai_demo_docs_logic/venv_setup/__pycache__/py.cpython-312.pyc +0 -0
  115. api_logic_server_cli/sqlacodegen_wrapper/__pycache__/__init__.cpython-312.pyc +0 -0
  116. api_logic_server_cli/sqlacodegen_wrapper/__pycache__/sqlacodegen_wrapper.cpython-312.pyc +0 -0
  117. api_logic_server_cli/sqlacodegen_wrapper/sqlacodegen/__pycache__/__init__.cpython-312.pyc +0 -0
  118. api_logic_server_cli/sqlacodegen_wrapper/sqlacodegen/sqlacodegen/__pycache__/__init__.cpython-312.pyc +0 -0
  119. api_logic_server_cli/sqlacodegen_wrapper/sqlacodegen/sqlacodegen/__pycache__/codegen.cpython-312.pyc +0 -0
  120. {apilogicserver-15.0.47.dist-info → apilogicserver-15.0.54.dist-info}/WHEEL +0 -0
  121. {apilogicserver-15.0.47.dist-info → apilogicserver-15.0.54.dist-info}/entry_points.txt +0 -0
  122. {apilogicserver-15.0.47.dist-info → apilogicserver-15.0.54.dist-info}/licenses/LICENSE +0 -0
  123. {apilogicserver-15.0.47.dist-info → apilogicserver-15.0.54.dist-info}/top_level.txt +0 -0
@@ -12,10 +12,12 @@ ApiLogicServer CLI: given a database url, create [and run] customizable ApiLogic
12
12
  Called from api_logic_server_cli.py, by instantiating the ProjectRun object.
13
13
  '''
14
14
 
15
- __version__ = "15.00.47" # last public release: 15.00.41 (15.00.12)
15
+ __version__ = "15.00.54" # last public release: 15.00.52 (15.00.12)
16
16
  recent_changes = \
17
17
  f'\n\nRecent Changes:\n' +\
18
- "\t07/14/2024 - 15.00.47: venv fix, copilot vibe tweaks - creation, mcp logic, basic_demo autonums \n"\
18
+ "\t07/23/2024 - 15.00.54: system vibe support \n"\
19
+ "\t07/20/2024 - 15.00.52: Python 3.13 compatibility fixes - psycopg2→psycopg3, SQLAlchemy 2.0+, pkg_resources→importlib.metadata. mgr dbs \n"\
20
+ "\t07/17/2024 - 15.00.49: venv fix+, ext bldr * fix, copilot vibe tweaks - creation, mcp logic, basic_demo autonums \n"\
19
21
  "\t07/10/2024 - 15.00.41: copilot vibe support for logic, UI, MCP, bug[98] \n"\
20
22
  "\t06/30/2024 - 15.00.33: Tech Preview: genai-logic genai-add-app --vibe, bug [96, 97] \n"\
21
23
  "\t06/10/2024 - 15.00.12: MCP Security, win fixes for readme, graphics quotes \n"\
@@ -389,6 +391,7 @@ def create_project_and_overlay_prototypes(project: 'ProjectRun', msg: str) -> st
389
391
  joinpath('prototypes/basic_demo')
390
392
  recursive_overwrite(nw_dir, project.project_directory)
391
393
  create_utils.copy_md(project = project, from_doc_file = "Sample-Basic-Demo.md")
394
+ create_utils.copy_md(project = project, from_doc_file = "Sample-Basic-Demo-Vibe.md", to_project_file="README-VIBE.md")
392
395
 
393
396
 
394
397
  if project.db_url == "mysql+pymysql://root:p@localhost:3306/classicmodels":
@@ -463,6 +466,13 @@ def create_project_and_overlay_prototypes(project: 'ProjectRun', msg: str) -> st
463
466
  copy_sqlite = True
464
467
  if copy_sqlite == False or "sqlite" not in project.abs_db_url:
465
468
  db_uri = get_windows_path_with_slashes(project.abs_db_url)
469
+
470
+ # Convert PostgreSQL URL for Python 3.13+ compatibility
471
+ import sys
472
+ if sys.version_info >= (3, 13) and db_uri.startswith('postgresql://'):
473
+ db_uri = db_uri.replace('postgresql://', 'postgresql+psycopg://')
474
+ log.debug(f'.. ..Converted PostgreSQL URL for Python 3.13+: {db_uri}')
475
+
466
476
  create_utils.replace_string_in_file(search_for="replace_db_url",
467
477
  replace_with=db_uri,
468
478
  in_file=f'{project.project_directory}/config/config.py')
@@ -915,7 +925,10 @@ def start_open_with(project: Project):
915
925
 
916
926
  def invoke_extended_builder(builder_path, db_url, project_directory, model_creation_services):
917
927
  # spec = importlib.util.spec_from_file_location("module.name", "/path/to/file.py")
918
- spec = importlib.util.spec_from_file_location("module.name", builder_path)
928
+ use_builder_path = builder_path
929
+ if builder_path == '*':
930
+ use_builder_path = Path('extended_builder.py')
931
+ spec = importlib.util.spec_from_file_location("module.name", use_builder_path)
919
932
  extended_builder = importlib.util.module_from_spec(spec)
920
933
  spec.loader.exec_module(extended_builder) # runs "bare" module code (e.g., initialization)
921
934
  extended_builder.extended_builder(db_url, project_directory, model_creation_services) # extended_builder.MyClass()
@@ -1194,8 +1207,8 @@ class ProjectRun(Project):
1194
1207
  log.debug(f'.. .. ..Copying sqlite database to: database/{self.bind_key}_db.sqlite')
1195
1208
  db_loc = self.abs_db_url.replace("sqlite:///", "")
1196
1209
  if os.name == "nt":
1197
- if db_loc.startswith("C:\C:"): # windows
1198
- db_loc = db_loc.replace("C:\C:", "C:") # remove unk junk
1210
+ if db_loc.startswith(r"C:\C:"): # windows
1211
+ db_loc = db_loc.replace(r"C:\C:", "C:") # remove unk junk
1199
1212
  target_db_loc_actual = str(self.project_directory_path.joinpath(f'database/{self.bind_key}_db.sqlite'))
1200
1213
  # target: /Users/val/dev/ApiLogicServer/ApiLogicServer-dev/org_git/servers/NW_NoCust/database/Todo_db.sqlite
1201
1214
  # e.g., /Users/val/dev/ApiLogicServer/ApiLogicServer-dev/servers/NW_NoCust/database
@@ -1,3 +1,3 @@
1
- last_created_date: July 14, 2025 19:56:50
2
- last_created_project_name: ApiLogicProject
3
- last_created_version: 15.00.46
1
+ last_created_date: July 23, 2025 12:12:14
2
+ last_created_project_name: ../../../servers/basic_demo
3
+ last_created_version: 15.00.53
@@ -188,14 +188,16 @@ def main(ctx):
188
188
  Creation is from your database (--db-url identifies a SQLAlchemy database)
189
189
 
190
190
  \b
191
- Doc: https://apilogicserver.github.io/Docs
191
+ Synonym to genai-logic: gail | gal
192
+ \b
193
+ Doc: https://apilogicserver.github.io/Docs/Doc-Home/
192
194
  And: https://apilogicserver.github.io/Docs/Database-Connectivity/
193
195
  \b
194
196
  Suggestions:
195
197
 
196
198
  \b
197
- ApiLogicServer start # create and manage projects
198
- ApiLogicServer create --db-url= --project-name= # defaults to Northwind sample
199
+ genai-logic start # create and manage projects
200
+ genai-logic create --db-url= --project-name= # defaults to Northwind sample
199
201
  """
200
202
  pass # all commands come through here
201
203
 
@@ -1083,13 +1085,13 @@ def genai_iterate(ctx, project_name: str, using: str):
1083
1085
  help="your_code.py for additional build automation")
1084
1086
  @click.option('--include_tables',
1085
1087
  default=f'',
1086
- help="yml for include: exclude:")
1088
+ help="yml for include, exclude")
1087
1089
  @click.option('--include-tables', 'include_tables',
1088
1090
  default=f'',
1089
- help="yml for include: exclude:")
1091
+ help="yml for include, exclude")
1090
1092
  @click.option('--infer_primary_key/--no_infer_primary_key',
1091
1093
  default=False, is_flag=True,
1092
- help="xInfer primary_key for unique cols")
1094
+ help="Infer primary_key for unique cols")
1093
1095
  @click.option('--infer-primary-key/--no-infer-primary-key', 'infer_primary_key',
1094
1096
  default=False, is_flag=True,
1095
1097
  help="Infer primary-key for unique cols")
@@ -1250,22 +1252,22 @@ def create(ctx, project_name: str, db_url: str, not_exposed: str, api_name: str,
1250
1252
  help="Swagger hostname (default is localhost)")
1251
1253
  @click.option('--extended_builder',
1252
1254
  default=f'',
1253
- help="your_code.py for additional build automation")
1255
+ help="your python for additional build automation")
1254
1256
  @click.option('--extended-builder', 'extended_builder',
1255
1257
  default=f'',
1256
- help="your_code.py for additional build automation")
1258
+ help="your python for additional build automation")
1257
1259
  @click.option('--include_tables',
1258
1260
  default=f'',
1259
- help="yml for include: exclude:")
1261
+ help="yml for include / exclude")
1260
1262
  @click.option('--include-tables', 'include_tables',
1261
1263
  default=f'',
1262
- help="yml for include: exclude:")
1264
+ help="yml for include / exclude")
1263
1265
  @click.option('--infer_primary_key/--no_infer_primary_key',
1264
1266
  default=False, is_flag=True,
1265
- help="Infer primary-key for unique cols")
1267
+ help="Infer primary key for unique cols")
1266
1268
  @click.option('--infer-primary-key/--no-infer-primary-key', 'infer_primary_key',
1267
1269
  default=False, is_flag=True,
1268
- help="Infer primary-key for unique cols")
1270
+ help="Unique cols infer primary key")
1269
1271
  @click.pass_context
1270
1272
  def create_and_run(ctx, project_name: str, db_url: str, not_exposed: str, api_name: str,
1271
1273
  from_git: str,
@@ -1280,11 +1282,13 @@ def create_and_run(ctx, project_name: str, db_url: str, not_exposed: str, api_na
1280
1282
  host: str,
1281
1283
  port: str,
1282
1284
  swagger_host: str,
1283
- favorites: str, non_favorites: str,
1285
+ favorites: str,
1286
+ non_favorites: str,
1284
1287
  extended_builder: str,
1285
1288
  include_tables: str,
1286
1289
  multi_api: click.BOOL,
1287
- opt_locking: str, opt_locking_attr: str,
1290
+ opt_locking: str,
1291
+ opt_locking_attr: str,
1288
1292
  id_column_alias: str,
1289
1293
  infer_primary_key: click.BOOL):
1290
1294
  """
@@ -2122,7 +2126,7 @@ if __name__ == '__main__': # debugger & python command line start here
2122
2126
  "show-args" in api_logic_server_info_file_dict:
2123
2127
  print_args(commands, f'\nCommand Line Arguments:')
2124
2128
  python_version = sys.version_info
2125
- assert python_version[0] >= 3 and python_version[1] in [10,11,12], \
2126
- "... Requires Python >=3.10, !=3.11.0, !=3.11.1, 3.12"
2129
+ assert python_version[0] >= 3 and python_version[1] in [10,11,12, 13], \
2130
+ "... Requires Python >=3.10, !=3.11.0, !=3.11.1, 3.12, 3.13"
2127
2131
  main()
2128
2132
 
@@ -197,6 +197,12 @@ def copy_md(project, from_doc_file: str, to_project_file: str = "README.md"):
197
197
  else:
198
198
  each_line = each_line.replace('.md', '') # hmm... todo: find out why this exists
199
199
  pass
200
+ if from_doc_file == 'Sample-Basic-Demo-Vibe.md' and 'title=' in each_line:
201
+ # extract the quoted text after 'title=' into title
202
+ match = re.search(r'title\s*=\s*["\']([^"\']+)["\']', each_line)
203
+ if match:
204
+ title = match.group(1)
205
+ readme_lines_md.append('**' + title + ':**\n')
200
206
  readme_lines_md.append(each_line)
201
207
  with open(str(to_file), "w") as readme_file:
202
208
  readme_file.writelines(readme_lines_md)
@@ -293,10 +299,13 @@ def get_abs_db_url(msg, project: Project, is_auth: bool = False):
293
299
  else:
294
300
  rtn_abs_db_url = f'sqlite:///{str(project.api_logic_server_dir_path.joinpath("prototypes/sample_ai/database/chatgpt/sample_ai_items.sqlite"))}'
295
301
  # log.info('.. using installed nw sample database')
296
- else:
302
+ else: # for win, might be: sqlite:////C:\\Users\\val\\dev\\ApiLogicServer\\ApiLogicServer-dev\\org_git\\ApiLogicServer-src\\api_logic_server_cli\\database\\mcp.sqlite
297
303
  url = url_to_process[10: len(url_to_process)]
304
+ if url_to_process.startswith('sqlite:////c:'):
305
+ url = url_to_process[11: len(url_to_process)]
298
306
  rtn_abs_db_url = abspath(url)
299
307
  rtn_abs_db_url = 'sqlite:///' + rtn_abs_db_url
308
+ pass
300
309
  elif url_to_process == 'sqlsvr-sample': # work-around - VSCode run config arg parsing
301
310
  rtn_abs_db_url = 'mssql+pyodbc://sa:Posey3861@localhost:1433/SampleDB?driver=ODBC+Driver+18+for+SQL+Server&trusted_connection=no&Encrypt=no'
302
311
  elif url_to_process == 'sqlsvr-nwlogic': # work-around - VSCode run config arg parsing
@@ -36,9 +36,9 @@ def create_manager(clean: bool, open_with: str, api_logic_server_path: Path,
36
36
  samples (bool, optional): Whether to create large samples (prevent win max file length)
37
37
  """
38
38
 
39
- def create_sym_links(cli_path: Path, mgr_path: Path):
39
+ def copy_sqlite_dbs(cli_path: Path, mgr_path: Path):
40
40
  """
41
- Creates symbolic links to sample dbs and prompts (clearer than db abbreviations).
41
+ Copy sample sqlite databases to mgr/samples/dbs (clearer than db abbreviations).
42
42
 
43
43
  Args:
44
44
  cli_path (Path): loc of cli.py in the manager's venv
@@ -48,16 +48,27 @@ def create_manager(clean: bool, open_with: str, api_logic_server_path: Path,
48
48
  Creates a symbolic link from 'cli_path/database/basic_demo.sqlite' to 'mgr_path/samples/dbs/basic_demo'.
49
49
 
50
50
  """
51
-
52
- # create symbolic link - thanks https://www.geeksforgeeks.org/python/python-os-symlink-method/
53
- try:
54
- os.symlink(cli_path.parent / 'database/basic_demo.sqlite', mgr_path / 'samples/dbs/basic_demo.sqlite')
55
- os.symlink(cli_path.parent / 'database/nw-gold.sqlite', mgr_path / 'samples/dbs/nw.sqlite')
56
- os.symlink(cli_path.parent / 'database/Chinook_Sqlite.sqlite', mgr_path / 'samples/dbs/chinook.sqlite')
57
- os.symlink(cli_path.parent / 'database/classicmodels.sqlite', mgr_path / 'samples/dbs/classicmodels.sqlite')
58
- log.debug("✅ Manager Creation - SymLink created: samples/dbs/")
59
- except Exception as e:
60
- log.debug(f"❌ Manager Creation - SymLink creation failed: {str(e)}")
51
+ if use_syn_link := False:
52
+ # could create symbolic link - thanks https://www.geeksforgeeks.org/python/python-os-symlink-method/
53
+ # but this fails on windows due to permissions
54
+ try:
55
+ os.symlink(cli_path.parent / 'database/basic_demo.sqlite', mgr_path / 'samples/dbs/basic_demo.sqlite')
56
+ os.symlink(cli_path.parent / 'database/nw-gold.sqlite', mgr_path / 'samples/dbs/nw.sqlite')
57
+ os.symlink(cli_path.parent / 'database/Chinook_Sqlite.sqlite', mgr_path / 'samples/dbs/chinook.sqlite')
58
+ os.symlink(cli_path.parent / 'database/classicmodels.sqlite', mgr_path / 'samples/dbs/classicmodels.sqlite')
59
+ log.debug("✅ Manager Creation - SymLink created: samples/dbs/")
60
+ except Exception as e:
61
+ log.debug(f"❌ Manager Creation - Copy samples/dbs SymLink creation failed: {str(e)}")
62
+ else:
63
+ try:
64
+ copyfile(cli_path.parent / 'database/basic_demo.sqlite', mgr_path / 'samples/dbs/basic_demo.sqlite')
65
+ copyfile(cli_path.parent / 'database/nw-gold.sqlite', mgr_path / 'samples/dbs/nw.sqlite')
66
+ copyfile(cli_path.parent / 'database/Chinook_Sqlite.sqlite', mgr_path / 'samples/dbs/chinook.sqlite')
67
+ copyfile(cli_path.parent / 'database/classicmodels.sqlite', mgr_path / 'samples/dbs/classicmodels.sqlite')
68
+ copyfile(cli_path.parent / 'database/todos.sqlite', mgr_path / 'samples/dbs/todos.sqlite')
69
+ log.debug("✅ Manager Creation - Created: samples/dbs/")
70
+ except Exception as e:
71
+ log.debug(f"❌ Manager Creation - Copy samples/dbs creation failed: {str(e)}")
61
72
 
62
73
 
63
74
  log = logging.getLogger(__name__)
@@ -218,7 +229,7 @@ def create_manager(clean: bool, open_with: str, api_logic_server_path: Path,
218
229
  create_utils.replace_string_in_file(search_for = 'cli_path',
219
230
  replace_with=str(cli_str),
220
231
  in_file=vscode_launch_path)
221
- create_sym_links(cli_path=cli_path, mgr_path=to_dir)
232
+ copy_sqlite_dbs(cli_path=cli_path, mgr_path=to_dir)
222
233
 
223
234
  if env_path.exists():
224
235
  create_utils.replace_string_in_file(search_for = 'APILOGICSERVER_AUTO_OPEN=code',
@@ -37,11 +37,14 @@ python api_logic_server_run.py
37
37
  Rule.sum(derive=Customer.Balance, as_sum_of=Order.AmountTotal)
38
38
  Rule.constraint(validate=Customer, as_condition=lambda row: row.Balance <= row.CreditLimit)
39
39
  ```
40
+
41
+ As described in `docs/training/logic_bank_api.prompt`, logic includes rules for sums, formulas, constraints, and more. They also include events, which are used to trigger actions like sending emails or updating related records.
42
+
40
43
  For project `basic_demo`, the best place to begin is to provide CoPilot with the natural language logic below. CoPilot will then offer to translate the logic into LogicBank rules. Also
41
44
  1. Provide the analysis (below) showing the 44X code reduction.
42
45
  2. Stress the importance of business logic - it's half the project, and requires an underlying rules engine. Using AI alone is not sufficient - you will wind up with procedural code, with the issues noted in the analysis below.
43
46
 
44
- Here's the natural language logic to provide to CoPilotP
47
+ Here's the natural language logic to provide to CoPilot:
45
48
 
46
49
  ```text
47
50
  Use case: Check Credit
@@ -126,6 +129,8 @@ Then, `npm install` and `npm start`
126
129
 
127
130
  Temporary restriction: security must be disabled.
128
131
 
132
+ **IMPORTANT**: When working with React apps, ALWAYS read `docs/training` first. This file contains critical data access provider configuration that was built when the project was created. The data provider handles JSON:API communication and record context - ignore this at your peril.
133
+
129
134
  Customize using CoPilot chat, with `docs/training`.
130
135
 
131
136
  ### Security - Role-Based Access Control
@@ -164,9 +169,13 @@ def my_endpoint():
164
169
  return {"message": "Custom endpoint"}
165
170
  ```
166
171
 
167
- ### Customize Models - Add Attributes
172
+ ### Customize Models - Add Tables, Attributes
173
+
174
+ Update `database/model.py`, and use `database/alembic` to update the database (highly impactful - request permission). This is *generally* preferrable to updating the database directly, since some platforms may not have database CLI tools.
168
175
 
169
- Update the model, and use `database/alembic` to update the database (highly impactful - request permission).
176
+ If altering `database/models.py`, be sure to follow the patterns shown in the existing models. Note they not typically contain a `__bind_key__`.
177
+
178
+ ```python
170
179
 
171
180
  ### Addressing `Missing Attributes` during logic loading at project startup
172
181
 
@@ -216,6 +225,33 @@ Convert to Python values first using float(), int(), str()
216
225
  Use property() function instead of @jsonapi_attr for computed properties
217
226
  Always add error handling for type conversions
218
227
 
228
+ ### Adding events
229
+ LogicBank rules are the preferred approach to logic, but you will sometimes need to add events. This is done in `logic/declare_logic.py` (important: the function MUST come first):
230
+
231
+ ```python
232
+ # Example: Log email activity after SysEmail is committed
233
+
234
+ def sys_email_after_commit(row: models.SysEmail, old_row: models.SysEmail, logic_row: LogicRow):
235
+ """
236
+ After SysEmail is committed, log 'email sent'
237
+ unless the customer has opted out
238
+ """
239
+ if not row.customer.email_opt_out:
240
+ logic_row.log(f"📧 Email sent to {row.customer.name} - Subject: {row.subject}")
241
+ else:
242
+ logic_row.log(f"🚫 Email blocked for {row.customer.name} - Customer opted out")
243
+
244
+ Rule.commit_row_event(on_class=SysEmail, calling=sys_email_after_commit)
245
+ ```
246
+
247
+ LogicBank event types include:
248
+ - `Rule.commit_row_event()` - fires after transaction commits
249
+ - `Rule.after_insert()` - fires after row insert
250
+ - `Rule.after_update()` - fires after row update
251
+ - `Rule.after_delete()` - fires after row delete
252
+
253
+ All events receive `(row, old_row, logic_row)` parameters and should use `logic_row.log()` for logging.
254
+
219
255
  ## 📁 Key Directories
220
256
 
221
257
  - `logic/` - Business rules (declarative)
@@ -133,6 +133,12 @@ class Config:
133
133
  SQLALCHEMY_DATABASE_URI : typing.Optional[str] = f"replace_db_url"
134
134
  # override SQLALCHEMY_DATABASE_URI here as required
135
135
 
136
+ # Python 3.13+ compatibility: Convert PostgreSQL URLs to use psycopg3
137
+ import sys
138
+ if sys.version_info >= (3, 13) and SQLALCHEMY_DATABASE_URI.startswith('postgresql://'):
139
+ SQLALCHEMY_DATABASE_URI = SQLALCHEMY_DATABASE_URI.replace('postgresql://', 'postgresql+psycopg://')
140
+ app_logger.debug(f'config.py - converted PostgreSQL URL for Python 3.13+: {SQLALCHEMY_DATABASE_URI}')
141
+
136
142
  BACKTIC_AS_QUOTE = False # use backtic as quote for table names for API Bridge
137
143
  if SQLALCHEMY_DATABASE_URI.startswith("mysql") or SQLALCHEMY_DATABASE_URI.startswith("mariadb"):
138
144
  BACKTIC_AS_QUOTE = True
@@ -145,6 +151,11 @@ class Config:
145
151
  if os.getenv('SQLALCHEMY_DATABASE_URI'): # e.g. export SECURITY_ENABLED=true
146
152
  SQLALCHEMY_DATABASE_URI = os.getenv('SQLALCHEMY_DATABASE_URI')
147
153
  app_logger.debug(f'.. overridden from env variable: {SQLALCHEMY_DATABASE_URI}')
154
+
155
+ # Python 3.13+ compatibility: Convert PostgreSQL URLs to use psycopg3 (for env override)
156
+ if sys.version_info >= (3, 13) and SQLALCHEMY_DATABASE_URI.startswith('postgresql://'):
157
+ SQLALCHEMY_DATABASE_URI = SQLALCHEMY_DATABASE_URI.replace('postgresql://', 'postgresql+psycopg://')
158
+ app_logger.debug(f'config.py - converted PostgreSQL URL for Python 3.13+: {SQLALCHEMY_DATABASE_URI}')
148
159
 
149
160
 
150
161
  # KEYCLOAK Args
@@ -178,6 +189,10 @@ class Config:
178
189
  # Begin Multi-Database URLs (from ApiLogicServer add-db...)
179
190
  auth_db_path = str(project_path.joinpath('database/authentication_db.sqlite'))
180
191
  SQLALCHEMY_DATABASE_URI_AUTHENTICATION = f'sqlite:///{auth_db_path}'
192
+ # Python 3.13+ compatibility: Convert PostgreSQL URLs to use psycopg3 (for env override)
193
+ if sys.version_info >= (3, 13) and SQLALCHEMY_DATABASE_URI_AUTHENTICATION.startswith('postgresql://'):
194
+ SQLALCHEMY_DATABASE_URI_AUTHENTICATION = SQLALCHEMY_DATABASE_URI_AUTHENTICATION.replace('postgresql://', 'postgresql+psycopg://')
195
+ app_logger.debug(f'config.py - converted PostgreSQL URL for Python 3.13+: {SQLALCHEMY_DATABASE_URI_AUTHENTICATION}')
181
196
  app_logger.info(f'config.py - SQLALCHEMY_DATABASE_URI_AUTHENTICATION: {SQLALCHEMY_DATABASE_URI_AUTHENTICATION}\n')
182
197
 
183
198
  # as desired, use env variable: export SQLALCHEMY_DATABASE_URI='sqlite:////Users/val/dev/servers/docker_api_logic_project/database/db.sqliteXX'
@@ -0,0 +1,98 @@
1
+ import os
2
+ import subprocess
3
+ import sys
4
+
5
+ '''
6
+ Pushes the current database/models.py to the database.
7
+ python database/alembic/alembic_run.py [--non-interactive]
8
+ '''
9
+
10
+ def prompt(msg, non_interactive=False):
11
+ if non_interactive:
12
+ print(f"{msg}")
13
+ print("Running in non-interactive mode...")
14
+ return
15
+ try:
16
+ input(f"{msg}\nPress Enter to continue or Ctrl+C to abort...")
17
+ except EOFError:
18
+ print("Running in non-interactive mode (no stdin available)...")
19
+ return
20
+
21
+ def run(cmd, env=None):
22
+ print(f"Running: {cmd}")
23
+ result = subprocess.run(cmd, shell=True, env=env)
24
+ if result.returncode != 0:
25
+ print(f"Command failed: {cmd}")
26
+ sys.exit(result.returncode)
27
+
28
+ def main():
29
+ # Check for non-interactive mode more safely
30
+ non_interactive = "--non-interactive" in sys.argv
31
+ if not non_interactive:
32
+ try:
33
+ non_interactive = not sys.stdin.isatty()
34
+ except:
35
+ # If we can't check stdin, assume non-interactive
36
+ non_interactive = True
37
+
38
+ orig_dir = os.getcwd()
39
+ # Change to the database directory (parent of alembic directory) where alembic.ini is located
40
+ db_dir = os.path.dirname(os.path.dirname(os.path.abspath(__file__)))
41
+ print(f"Changing directory to {db_dir}")
42
+ os.chdir(db_dir)
43
+
44
+ env = os.environ.copy()
45
+ env["APILOGICPROJECT_NO_FLASK"] = "True" # ~ export APILOGICPROJECT_NO_FLASK=True
46
+
47
+ print("\n\nThis script will update your database schema to match models.py using Alembic.")
48
+ print("Steps:")
49
+ print("1. Set APILOGICPROJECT_NO_FLASK=True -- eg, export APILOGICPROJECT_NO_FLASK=True")
50
+ print("2. Run: alembic upgrade head")
51
+ print("3. Run: alembic revision --autogenerate -m \"message\"")
52
+ prompt("Ready to proceed?", non_interactive)
53
+
54
+ run("alembic upgrade head", env=env)
55
+ print("Database schema updated to latest migration.")
56
+
57
+ prompt("Now, a new migration will be generated to match models.py.", non_interactive)
58
+ if non_interactive:
59
+ msg = "autogenerated"
60
+ else:
61
+ try:
62
+ msg = input("Enter a message for the migration (default: 'autogenerated'): ") or "autogenerated"
63
+ except EOFError:
64
+ msg = "autogenerated"
65
+ run(f'alembic revision --autogenerate -m "{msg}"', env=env)
66
+
67
+ # Find the latest migration file
68
+ versions_dir = os.path.join(db_dir, "alembic", "versions")
69
+ migration_files = sorted(
70
+ [f for f in os.listdir(versions_dir) if f.endswith(".py")],
71
+ key=lambda x: os.path.getmtime(os.path.join(versions_dir, x)),
72
+ reverse=True
73
+ )
74
+ if migration_files:
75
+ latest_file = os.path.join(versions_dir, migration_files[0])
76
+ with open(latest_file, "r") as f:
77
+ lines = f.readlines()
78
+ with open(latest_file, "w") as f:
79
+ for line in lines:
80
+ f.write(line)
81
+ if line.strip().startswith("def downgrade"):
82
+ f.write(" return\n")
83
+ break
84
+ else:
85
+ print("No migration file found.")
86
+ sys.exit(1)
87
+
88
+ # Apply the newly generated migration after modifying the migration file
89
+ prompt(f"Migration file generated: {latest_file}\nIt is recommended to review this migration file before proceeding.", non_interactive)
90
+ run("alembic upgrade head", env=env)
91
+
92
+ print("Migration file updated: downgrade will do nothing.")
93
+ print("Consider updating ui/admin/admin.yaml to reflect schema changes.")
94
+ os.chdir(orig_dir)
95
+ print("\nSuccess! Database schema and migrations are up to date.\n\n")
96
+
97
+ if __name__ == "__main__":
98
+ main()
@@ -0,0 +1,36 @@
1
+ You can push changes to `database/models.py' to your database automatically, or manually.
2
+
3
+ <br>
4
+
5
+ ## Automatic
6
+
7
+ Use:
8
+
9
+ ```bash
10
+ python database/alembic/alembic_run.py [--non-interactive]
11
+ ```
12
+
13
+ <br>
14
+
15
+ ## Manual
16
+
17
+ The diagram below illustrates a path for enacting changes to the data model, and using [Alembic](https://alembic.sqlalchemy.org/en/latest/index.html) to automate the database changes:
18
+
19
+ 1. Update `database/models.py` (e.g., add columns, tables)
20
+ 2. Use alembic to compute the revisions
21
+ ```bash
22
+ cd database
23
+ export APILOGICPROJECT_NO_FLASK=True
24
+ alembic revision --autogenerate -m "Added Tables and Columns"
25
+ ```
26
+ 3. **Edit the revision file** to signify your understanding (see below)
27
+ 4. Activate the change
28
+ ```bash
29
+ alembic upgrade head
30
+ unset APILOGICPROJECT_NO_FLASK
31
+ ```
32
+
33
+ ![alembic example](https://github.com/ApiLogicServer/Docs/blob/main/docs/images/database/alembic/alembic-overview.png?raw=true)
34
+
35
+
36
+ To update your admin app, run `rebuild-from-model`. For more information, see [Database Design Changes](https://apilogicserver.github.io/Docs/Database-Changes/).
@@ -1,3 +1,43 @@
1
1
 
2
2
  Generate a full React Admin application using the following instructions.
3
3
  The result must be a runnable React app (`npm start`) that connects to the supplied JSON:API, with fully implemented components (no placeholders or empty files).
4
+
5
+ ## Critical Data Access Provider Configuration
6
+
7
+ This project uses a **pre-configured JSON:API data provider** that was built when the project was created.
8
+
9
+ ### Key Requirements:
10
+
11
+ 1. **Data Provider**: Use the existing `jsonapiClient` from `./rav4-jsonapi-client/ra-jsonapi-client`
12
+ 2. **Record Context**: For custom components (like cards), ALWAYS wrap with `<RecordContextProvider value={record}>`
13
+ 3. **List Data Access**: Use `useListContext()` to get data and loading state
14
+ 4. **Individual Records**: Use `useRecordContext()` to access record data within providers
15
+ 5. **API Root**: The data provider connects to `conf.api_root` (typically `http://localhost:5656/api`)
16
+
17
+ ### Example Pattern for Custom List Views:
18
+ ```javascript
19
+ import { useListContext, RecordContextProvider, useRecordContext } from 'react-admin';
20
+
21
+ const CustomGrid = () => {
22
+ const { data, isLoading } = useListContext();
23
+
24
+ return (
25
+ <Grid container>
26
+ {data?.map(record => (
27
+ <Grid item key={record.id}>
28
+ <RecordContextProvider value={record}>
29
+ <CustomCard />
30
+ </RecordContextProvider>
31
+ </Grid>
32
+ ))}
33
+ </Grid>
34
+ );
35
+ };
36
+
37
+ const CustomCard = () => {
38
+ const record = useRecordContext();
39
+ return <Card>{record.name}</Card>;
40
+ };
41
+ ```
42
+
43
+ ### CRITICAL: Do NOT create new data providers or modify the existing JSON:API client configuration. The project's data flow depends on the pre-built provider.
@@ -147,12 +147,12 @@ def query_llm_with_nl(learnings_and_schema: str, nl_query: str):
147
147
  else:
148
148
  # read integration/mcp/mcp_tool_context.json
149
149
  tool_context_file_path = os.path.join(os.path.dirname(__file__), "../../integration/mcp/examples/mcp_tool_context_response_get.json")
150
- if nl_query == default_query_email:
150
+ if 'send email' in nl_query:
151
151
  tool_context_file_path = os.path.join(os.path.dirname(__file__), "../../integration/mcp/examples/mcp_tool_context_response.json")
152
152
  try:
153
153
  with open(tool_context_file_path, "r") as tool_context_file:
154
154
  tool_context_str = tool_context_file.read()
155
- # log.info(f"\n\n2c. Tool context from file {tool_context_file_path}:\n" + tool_context_str)
155
+ log.info(f"\n\n2c. Tool context from file {tool_context_file_path}:\n" + tool_context_str)
156
156
  except FileNotFoundError:
157
157
  raise ConstraintException(f"Tool context file not found at {tool_context_file_path}.")
158
158
 
@@ -1,9 +1,9 @@
1
1
  PyJWT==2.6.0
2
2
  python-dateutil==2.8.2
3
3
  six==1.16.0
4
- SQLAlchemy==1.4.29
5
- Flask-SQLAlchemy==2.5.1
6
- SQLAlchemy-Utils==0.38.2
4
+ SQLAlchemy>=2.0.0
5
+ Flask-SQLAlchemy>=3.0.0
6
+ SQLAlchemy-Utils>=0.38.2
7
7
  Werkzeug==2.2.3
8
8
  logicbankutils==0.6.0
9
9
  inflect==5.0.2
@@ -25,7 +25,8 @@ PyMySQL==1.0.2
25
25
  cryptography==36.0.1
26
26
  requests==2.27.1
27
27
  gunicorn==20.1.0
28
- psycopg2-binary==2.9.5
28
+ psycopg2-binary>=2.9.5; python_version < '3.13'
29
+ psycopg[binary]>=3.1.0; python_version >= '3.13'
29
30
  DotMap==1.3.25
30
31
  WTForms==2.3.3
31
32
  behave==1.2.6
@@ -0,0 +1,8 @@
1
+ # GitHub Pages / Jekyll Configuration
2
+ # Enable processing of markdown files
3
+ markdown: kramdown
4
+ highlighter: rouge
5
+
6
+ # Include the _layouts directory
7
+ include:
8
+ - _layouts
@@ -0,0 +1,15 @@
1
+ <!DOCTYPE html>
2
+ <html>
3
+ <head>
4
+ <meta charset="utf-8" />
5
+ <meta http-equiv="refresh" content="1;url={{ page.redirect }}" />
6
+ <link rel="canonical" href="{{ page.redirect }}" />
7
+ <script type="text/javascript">
8
+ window.location.href = "{{ page.redirect }}"
9
+ </script>
10
+ <title>Page Redirection</title>
11
+ </head>
12
+ <body>
13
+ If you are not redirected automatically, follow <a href='{{ page.redirect }}'>this link</a>.
14
+ </body>
15
+ </html>