ApiLogicServer 15.0.28__py3-none-any.whl → 15.0.33__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 (46) hide show
  1. api_logic_server_cli/add_cust/add_cust.py +4 -4
  2. api_logic_server_cli/api_logic_server.py +20 -5
  3. api_logic_server_cli/api_logic_server_info.yaml +3 -3
  4. api_logic_server_cli/cli.py +61 -10
  5. api_logic_server_cli/cli_args_base.py +1 -1
  6. api_logic_server_cli/create_from_model/__pycache__/dbml.cpython-312.pyc +0 -0
  7. api_logic_server_cli/create_from_model/__pycache__/ont_create.cpython-312.pyc +0 -0
  8. api_logic_server_cli/create_from_model/dbml.py +1 -1
  9. api_logic_server_cli/create_from_model/ont_create.py +6 -1
  10. api_logic_server_cli/database/mcp.sqlite +0 -0
  11. api_logic_server_cli/fragments/mcp_admin.yml +11 -0
  12. api_logic_server_cli/genai/genai_admin_app.py +67 -19
  13. api_logic_server_cli/genai/genai_mcp.py +43 -0
  14. api_logic_server_cli/genai/genai_svcs.py +13 -12
  15. api_logic_server_cli/manager.py +29 -2
  16. api_logic_server_cli/prototypes/base/config/default.env +3 -0
  17. api_logic_server_cli/prototypes/base/devops/docker-compose-dev-azure/azure-deploy.sh +3 -3
  18. api_logic_server_cli/prototypes/base/devops/docker-compose-dev-local/docker-compose.sh +1 -1
  19. api_logic_server_cli/prototypes/base/ui/admin/admin_loader.py +2 -0
  20. api_logic_server_cli/prototypes/basic_demo/README.md +1 -1
  21. api_logic_server_cli/prototypes/basic_demo/customizations/database/db.sqlite +0 -0
  22. api_logic_server_cli/prototypes/basic_demo/customizations/database/models.py +0 -16
  23. api_logic_server_cli/prototypes/basic_demo/customizations/ui/admin/admin.yaml +0 -11
  24. api_logic_server_cli/prototypes/basic_demo/iteration/database/db.sqlite +0 -0
  25. api_logic_server_cli/prototypes/basic_demo/iteration/ui/admin/admin.yaml +4 -4
  26. api_logic_server_cli/prototypes/manager/README.md +1 -1
  27. api_logic_server_cli/prototypes/manager/samples/dbs/readme_samples.md +5 -0
  28. api_logic_server_cli/prototypes/manager/samples/readme_samples.md +3 -0
  29. api_logic_server_cli/prototypes/manager/system/app_model_editor/devops/docker-compose-dev-azure/azure-deploy.sh +1 -1
  30. api_logic_server_cli/prototypes/manager/system/app_model_editor/devops/docker-compose-dev-local-nginx/docker-compose.sh +1 -1
  31. api_logic_server_cli/prototypes/manager/system/genai/examples/genai_demo/genai_demo_docs_logic/devops/docker-compose-dev-azure/azure-deploy.sh +1 -1
  32. api_logic_server_cli/prototypes/manager/system/genai/examples/genai_demo/genai_demo_docs_logic/devops/docker-compose-dev-local/docker-compose.sh +1 -1
  33. api_logic_server_cli/prototypes/nw_no_cust/Tutorial.md +2 -2
  34. api_logic_server_cli/prototypes/sqlite/devops/docker-compose-dev-azure/azure-deploy.sh +1 -1
  35. api_logic_server_cli/{prototypes/basic_demo/customizations/logic/logic_discovery → templates}/mcp_client_executor_request.py +4 -2
  36. {apilogicserver-15.0.28.dist-info → apilogicserver-15.0.33.dist-info}/METADATA +1 -1
  37. {apilogicserver-15.0.28.dist-info → apilogicserver-15.0.33.dist-info}/RECORD +41 -40
  38. apilogicserver-15.0.33.dist-info/entry_points.txt +7 -0
  39. api_logic_server_cli/genai/genai_admin_app copy.py +0 -150
  40. api_logic_server_cli/prototypes/manager/system/genai/app_templates/app_learning/Admin-App-Resource-Learning-Prompt copy.md +0 -203
  41. api_logic_server_cli/prototypes/manager/system/genai/app_templates/app_learning/notes.md +0 -7
  42. api_logic_server_cli/prototypes/manager/system/genai/app_templates/app_learning/z-unused-Admin-App-Learning-Prompt.md +0 -179
  43. apilogicserver-15.0.28.dist-info/entry_points.txt +0 -3
  44. {apilogicserver-15.0.28.dist-info → apilogicserver-15.0.33.dist-info}/WHEEL +0 -0
  45. {apilogicserver-15.0.28.dist-info → apilogicserver-15.0.33.dist-info}/licenses/LICENSE +0 -0
  46. {apilogicserver-15.0.28.dist-info → apilogicserver-15.0.33.dist-info}/top_level.txt +0 -0
@@ -158,7 +158,7 @@ def add_basic_demo_customizations(project: Project, do_show_messages: bool = Tru
158
158
  # log.info(".. curl -X 'POST' 'http://localhost:5656/api/SysMcp/' -H 'accept: application/vnd.api+json' -H 'Content-Type: application/json' -d '{ \"data\": { \"attributes\": {\"request\": \"List the orders date_shipped is null and CreatedOn before 2023-07-14, and send a discount email (subject: '\\''Discount Offer'\\'') to the customer for each one.\"}, \"type\": \"SysMcp\"}}'")
159
159
  log.info('')
160
160
  log.info(f'Next Steps: activate security')
161
- log.info(f'..ApiLogicServer add-auth --db_url=auth')
161
+ log.info(f'..genai-logic add-auth --db_url=auth')
162
162
  if project.is_tutorial == False:
163
163
  log.info(".. complete\n")
164
164
 
@@ -178,7 +178,7 @@ def add_basic_demo_iteration(project: Project, do_show_messages: bool = True, do
178
178
  create_utils.recursive_overwrite(nw_path, project.project_directory) # ~/dev/ApiLogicServer/ApiLogicServer-dev/servers/basic_demo
179
179
  if do_show_messages:
180
180
  log.info("\nNext Step:")
181
- log.info(f'..ApiLogicServer rebuild-from-database --db_url=sqlite:///database/db.sqlite')
181
+ log.info(f'..genai-logic rebuild-from-database --db_url=sqlite:///database/db.sqlite')
182
182
  log.info(".. complete\n")
183
183
 
184
184
 
@@ -210,7 +210,7 @@ def add_sample_ai_customizations(project: Project, do_show_messages: bool = True
210
210
  log.info(f'..logic/declare_logic.py')
211
211
  log.info(f'..security/declare_security.py\n')
212
212
  log.info(f'Next Steps: activate security')
213
- log.info(f'..ApiLogicServer add-auth --db_url=auth')
213
+ log.info(f'..genai-logic add-auth --db_url=auth')
214
214
  if project.is_tutorial == False:
215
215
  log.info(".. complete\n")
216
216
 
@@ -230,7 +230,7 @@ def add_sample_ai_iteration(project: Project, do_show_messages: bool = True, do_
230
230
  create_utils.recursive_overwrite(nw_path, project.project_directory) # '/Users/val/dev/ApiLogicServer/ApiLogicServer-dev/org_git/tutorial/1. Instant_Creation'
231
231
  if do_show_messages:
232
232
  log.info("\nNext Step:")
233
- log.info(f'..ApiLogicServer rebuild-from-database --project_name=./ --db_url=sqlite:///database/db.sqlite')
233
+ log.info(f'..genai-logic rebuild-from-database --project_name=./ --db_url=sqlite:///database/db.sqlite')
234
234
  log.info(".. complete\n")
235
235
 
236
236
 
@@ -12,10 +12,10 @@ 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.28" # last public release: 15.00.25 (15.00.12)
15
+ __version__ = "15.00.33" # last public release: 15.00.25 (15.00.12)
16
16
  recent_changes = \
17
17
  f'\n\nRecent Changes:\n' +\
18
- "\t06/26/2024 - 15.00.28: Tech Preview: als genai-app w/ sra provider+model+grid_cascadeAdd, imports+, bug [96] \n"\
18
+ "\t06/30/2024 - 15.00.33: Tech Preview: genai-logic genai-add-app --vibe, bug [96, 97] \n"\
19
19
  "\t06/10/2024 - 15.00.12: MCP Security, win fixes for readme, graphics quotes \n"\
20
20
  "\t06/08/2024 - 15.00.10: MCP, optional shortening of stacktrace lines, bugfix[92] \n"\
21
21
  "\t05/16/2024 - 14.05.00: safrs 3.1.7, running mcp preview \n"\
@@ -946,9 +946,16 @@ class ProjectRun(Project):
946
946
  defaultInterpreterPath = self.api_logic_server_dir_path.parent.parent.parent.joinpath('clean/ApiLogicServer/venv/bin/python')
947
947
  self.default_interpreter_path = defaultInterpreterPath
948
948
  """ used to compute manager_path """
949
- self.manager_path = self.default_interpreter_path.parent.parent.parent
950
- log.debug(f'.. ..Manager path: {self.manager_path}') # eg ApiLogicServer/ApiLogicServer-dev/clean/ApiLogicServer
951
- log.debug(f'.. ..Interp path: manager_path / venv/bin/python')
949
+ self.venv_path = Path(sys.prefix) if is_docker() == False else Path('/home/api_logic_server/api_logic_server_cli')
950
+ self.manager_path = self.venv_path.parent
951
+ check_system_genai = self.manager_path.joinpath('system/genai/temp')
952
+ if not check_system_genai.exists():
953
+ self.manager_path = (self.venv_path / '../api_logic_server_cli/prototypes/manager').resolve()
954
+ log.debug(f'.. ..Manager path from dev env - customizations not active') # eg ...ApiLogicServer-src/api_logic_server_cli/prototypes/manager
955
+ log.debug(f'.. ..Manager path: {self.manager_path}')
956
+ # log.debug(f'.. ..Interp path: {self.manager_path / 'venv/bin/python'}')
957
+ if sys.prefix == sys.base_prefix:
958
+ log.warning(f'.. ..Warning - venv not being used: {self.venv_path}')
952
959
 
953
960
  self.api_logic_server_home = self.api_logic_server_dir_path.parent
954
961
 
@@ -1591,6 +1598,14 @@ from database import <project.bind_key>_models
1591
1598
  log.debug("1. Not Deleting Existing Project")
1592
1599
  log.debug("2. Using Existing Project")
1593
1600
  if self.command == "add_db":
1601
+ check_bind_key_exists = 'DATABASE_URI_' + self.bind_key.upper()
1602
+ config_path = self.project_directory_path / 'config/config.py'
1603
+ bind_key_exists = create_utils.does_file_contain(in_file=config_path,
1604
+ search_for=check_bind_key_exists)
1605
+ if bind_key_exists and self.bind_key != 'authentication':
1606
+ log.error(f'\nLooks like database already added')
1607
+ log.error(f'..`{check_bind_key_exists}` found in `config/config.py`\n\n')
1608
+ sys.exit(1)
1594
1609
  self.abs_db_url = self.update_config_and_copy_sqlite_db(
1595
1610
  f".. ..Adding Database [{self.bind_key}] to existing project")
1596
1611
  else: # normal path - clone, [overlay nw]
@@ -1,3 +1,3 @@
1
- last_created_date: June 26, 2025 08:44:28
2
- last_created_project_name: ../../../servers/mycircles
3
- last_created_version: 15.00.26
1
+ last_created_date: June 30, 2025 09:36:49
2
+ last_created_project_name: samples/nw_sample_nocust
3
+ last_created_version: 15.00.32
@@ -12,6 +12,8 @@ To add a new arg:
12
12
  * update Project.run()
13
13
 
14
14
  Main code is api_logic_server.py (PR)
15
+
16
+ To expand commands: ctx.forward(existing_command))
15
17
  '''
16
18
 
17
19
  from contextlib import closing
@@ -447,7 +449,7 @@ def curl_test(ctx, message):
447
449
  help="App directory name")
448
450
  @click.option('--admin-app', 'admin_app',
449
451
  default='admin',
450
- help="Input admin app")
452
+ help="Input admin app (schema)")
451
453
  @click.pass_context
452
454
  def app_create(ctx, project_name, app, admin_app):
453
455
  """
@@ -778,13 +780,16 @@ def genai_graphics(ctx, using, genai_version: str, replace_with: str):
778
780
  pass
779
781
  log.info("")
780
782
 
781
-
782
-
783
-
784
- @main.command("genai-app", cls=HideDunderCommand)
783
+ @main.command("genai-add-app", cls=HideDunderCommand)
785
784
  @click.option('--app-name', 'app_name',
786
785
  default='react_app',
787
786
  help="Name of generated app in ui/")
787
+ @click.option('--vibe/--no-vibe',
788
+ default=True, is_flag=True,
789
+ help="Show vibe docs")
790
+ @click.option('--retries',
791
+ default=1,
792
+ help="lint retries - 1 means none (see setup)")
788
793
  @click.option('--schema',
789
794
  default='admin.yaml',
790
795
  help="Model file in ui/admin/")
@@ -792,9 +797,9 @@ def genai_graphics(ctx, using, genai_version: str, replace_with: str):
792
797
  default='gpt-4o',
793
798
  help="Eg, gpt-3.5-turbo, gpt-4o")
794
799
  @click.pass_context
795
- def genai_admin_app(ctx, app_name: str, schema: str, genai_version: str):
800
+ def genai_add_app(ctx, app_name: str, vibe: click.BOOL, retries: int, schema: str, genai_version: str):
796
801
  """
797
- Adds a customizable react app to project
802
+ Creates a customizable react app in ui/, ready for vibe
798
803
  """
799
804
  global command
800
805
  project_dir = resolve_blank_project_name('')
@@ -817,11 +822,57 @@ def genai_admin_app(ctx, app_name: str, schema: str, genai_version: str):
817
822
  log.info(f'... Typical usage - cd into project, use --project_name=. \n')
818
823
  exit (1)
819
824
  from api_logic_server_cli.genai.genai_admin_app import GenAIAdminApp
820
- genai_admin = GenAIAdminApp(project=project, app_name=app_name, schema=schema, genai_version=genai_version)
825
+ genai_admin = GenAIAdminApp(project=project, app_name=app_name, vibe=vibe, schema=schema, retries=retries, genai_version=genai_version)
826
+ pass
827
+ log.info("")
828
+
829
+
830
+ @main.command("genai-add-mcp-client", cls=HideDunderCommand)
831
+ @click.option('--admin-app', is_flag=True,
832
+ default=True,
833
+ help="Update Admin App")
834
+ @click.pass_context
835
+ def genai_add_mcp_client(ctx, admin_app: click.BOOL):
836
+ """
837
+ Adds mcp-client to project: db, logic, admin app
838
+ """
839
+ global command
840
+
841
+ project_name = resolve_blank_project_name('')
842
+ log.info("")
843
+
844
+ mcp_db_path = get_api_logic_server_path().joinpath("database/mcp.sqlite")
845
+ assert mcp_db_path.exists(), "Unable to find api_logic_server_cli/database/mcp.sqlite"
846
+ mcp_uri = fr"sqlite:////{str(mcp_db_path)}"
847
+ project = PR.ProjectRun(command="add_db",
848
+ project_name=project_name,
849
+ api_name='api',
850
+ db_url=mcp_uri,
851
+ bind_key='mcp',
852
+ bind_key_url_separator=default_bind_key_url_separator
853
+ )
854
+ print("MCP DB Added")
855
+
856
+ project.project_directory, project.api_name, project.merge_into_prototype = \
857
+ create_utils.get_project_directory_and_api_name(project)
858
+ project.project_directory_actual = os.path.abspath(os.getcwd()) # make path absolute, not relative (no /../)
859
+ project.project_directory_path = Path(project.project_directory_actual)
860
+ models_py_path = project.project_directory_path.joinpath('database/models.py')
861
+ project.abs_db_url, project.nw_db_status, project.model_file_name = \
862
+ create_utils.get_abs_db_url("0. Using Sample DB", project, is_auth=True)
863
+
864
+ if not models_py_path.exists():
865
+ log.info(f'... Error - does not appear to be a project: {str(project.project_directory_path)}')
866
+ log.info(f'... Typical usage - cd into project, use --project_name=. \n')
867
+ exit (1)
868
+ from api_logic_server_cli.genai.genai_mcp import GenMCP
869
+ genai_mcp = GenMCP(project=project, admin_app=admin_app, api_logic_server_path=get_api_logic_server_path())
821
870
  pass
871
+
822
872
  log.info("")
823
873
 
824
874
 
875
+
825
876
  @main.command("genai-create", cls=HideDunderCommand)
826
877
  @click.option('--project-name', 'project_name',
827
878
  default=f'{last_created_project_name}',
@@ -1386,7 +1437,7 @@ def rebuild_from_database(ctx, project_name: str, db_url: str, api_name: str, no
1386
1437
  \b
1387
1438
  ex
1388
1439
  \b
1389
- ApiLogicServer rebuild-from-database --project_name=~/dev/servers/ApiLogicProject --db_url=nw
1440
+ genai-logic rebuild-from-database --project_name=~/dev/servers/ApiLogicProject --db_url=nw
1390
1441
 
1391
1442
  """
1392
1443
  db_types = ""
@@ -2053,7 +2104,7 @@ def check_ports():
2053
2104
 
2054
2105
 
2055
2106
  def start(): # target of setup.py
2056
- sys.stdout.write("\nWelcome to API Logic Server " + PR.__version__ + "\n\n")
2107
+ sys.stdout.write("\nWelcome to Genai-Logic " + PR.__version__ + "\n\n")
2057
2108
  hostname, local_ip = check_ports() # = socket.gethostname()
2058
2109
  # sys.stdout.write(" SQLAlchemy Database URI help: https://docs.sqlalchemy.org/en/14/core/engines.html\n")
2059
2110
  main(obj={})
@@ -1,5 +1,5 @@
1
1
  from enum import Enum
2
-
2
+ from pathlib import Path
3
3
 
4
4
  class ExtendedEnum(Enum):
5
5
  """
@@ -210,7 +210,7 @@ class DBMLCreator(object):
210
210
  # copy mcp learning from manager (to enable user to extend)
211
211
  docs_path = Path(self.mod_gen.project_directory).joinpath('docs')
212
212
  docs_path.mkdir(parents=True, exist_ok=True)
213
- mcp_learning_src = genai_svcs.get_manager_path(use_env=True).joinpath('system/genai/mcp_learning')
213
+ mcp_learning_src = genai_svcs.get_manager_path(project=self.mod_gen.project).joinpath('system/genai/mcp_learning')
214
214
  mcp_learning_dst = Path(self.mod_gen.project_directory).joinpath('docs/mcp_learning')
215
215
  if mcp_learning_dst.exists():
216
216
  shutil.rmtree(mcp_learning_dst)
@@ -120,6 +120,11 @@ class OntCreator(object):
120
120
  if each_resource["hidden"] == True:
121
121
  continue
122
122
  each_entity = self.create_model_entity(each_resource, resources=resources)
123
+ is_missing = not each_resource_name in resources
124
+ if is_missing: # might occur with add-db
125
+ log.warning(f"\n⚠️ Warning - ont_create() finds admin.yaml resource '{each_resource_name}' - not present in database model")
126
+ log.warning(f"..Can occur when using multiple databases - update your ontimize app as required")
127
+ continue
123
128
  app_model_out.entities[each_resource_name] = each_entity
124
129
 
125
130
  app_model_out.entities[each_resource_name].columns = []
@@ -249,7 +254,7 @@ class OntCreator(object):
249
254
  if compute_type:
250
255
  is_missing = not each_resource_name in resources
251
256
  if is_missing: # might occur with add-db, using wrong model
252
- sys.exit(f"Sys Err - ont_create missing resource: {each_resource_name}\n\n")
257
+ sys.exit(f"Sys Err - ont_create missing resource: {each_resource_name}\n\n")
253
258
  else:
254
259
  resource = resources[each_resource_name]
255
260
  resource_attributes = resource.attributes
Binary file
@@ -0,0 +1,11 @@
1
+ mcp-SysMcp:
2
+ attributes:
3
+ - name: request
4
+ type: textarea
5
+ - label: ' id*'
6
+ name: id
7
+ search: true
8
+ sort: true
9
+ show_when: isInserting == false
10
+ type: SysMcp
11
+ user_key: id
@@ -6,7 +6,7 @@ from pathlib import Path
6
6
  import importlib
7
7
  from api_logic_server_cli.genai.genai_utils import call_chatgpt
8
8
  import requests
9
- import os, time
9
+ import os, time, sys
10
10
  import datetime
11
11
  import create_from_model.api_logic_server_utils as utils
12
12
  import time
@@ -27,6 +27,7 @@ import json
27
27
  from pathlib import Path
28
28
  from openai import OpenAI
29
29
  import yaml
30
+ import subprocess
30
31
  import api_logic_server_cli.genai.genai_svcs as genai_svcs
31
32
 
32
33
  log = logging.getLogger(__name__)
@@ -38,12 +39,15 @@ class JSResponseFormat(BaseModel): # must match system/genai/prompt_inserts/res
38
39
 
39
40
  class GenAIAdminApp:
40
41
 
41
- def __init__(self, project: Project, app_name: str, schema: str, genai_version: str):
42
+ def __init__(self, project: Project, app_name: str, vibe: bool, schema: str, genai_version: str, retries: int):
42
43
  self.start_time = time.time()
43
44
 
45
+ self.project = project
44
46
  self.api_version = genai_version
47
+ self.retries = retries
48
+
45
49
  self.project_root = project.project_directory_path
46
- self.app_templates_path = genai_svcs.get_manager_path(use_env=True).joinpath('system/genai/app_templates')
50
+ self.app_templates_path = genai_svcs.get_manager_path(project=project).joinpath('system/genai/app_templates')
47
51
 
48
52
  log.info(f'\ngenai_app here..')
49
53
  log.info(f'..model: {schema}')
@@ -56,13 +60,18 @@ class GenAIAdminApp:
56
60
  self.admin_yaml_path = self.project_root / f"ui/admin/{schema}"
57
61
  self.admin_config_prompt_path = self.app_templates_path / f"app_learning/Admin-config-prompt.md"
58
62
  self.admin_json_api_model_prompt_path = self.app_templates_path / f"app_learning/Admin-json-api-model-prompt.md"
59
- assert self.admin_config_prompt_path.exists(), "sys err - self.admin_config_prompt_path"
60
- assert self.admin_json_api_model_prompt_path.exists(), "sys err - self.admin_json_api_model_prompt_path"
63
+ if not self.admin_config_prompt_path.exists():
64
+ log.error('\nUnable to find Manager for app_learning/Admin-config-prompt.md')
65
+ log.error('..Please set env variable APILOGICSERVER_HOME to manager root\n')
66
+ sys.exit(1)
67
+ if not self.admin_json_api_model_prompt_path.exists():
68
+ log.error('\nUnable to find Manager for app_learning/Admin-json-api-model-prompt.md')
69
+ log.error('..Please set env variable APILOGICSERVER_HOME to manager root\n')
70
+ sys.exit(1)
61
71
 
62
72
  self.ui_project_path = self.project_root / f"ui/{app_name}"
63
73
  self.ui_src_path = self.ui_project_path / "src"
64
74
 
65
- self.app_templates_path = genai_svcs.get_manager_path(use_env=True).joinpath('system/genai/app_templates')
66
75
  self.react_admin_template_path = self.app_templates_path / 'react-admin-template'
67
76
  self.prompts_path = self.app_templates_path / "app_learning"
68
77
  # self.admin_app_learning = utils.read_file(self.prompts_path / "Admin-App-Learning-Prompt.md")
@@ -99,6 +108,8 @@ class GenAIAdminApp:
99
108
  log.info(f'> cd ui/{app_name}')
100
109
  log.info('> npm install')
101
110
  log.info('> npm start\n')
111
+ if vibe:
112
+ log.info('\n💡 Suggestion: Customize with Vibe: https://apilogicserver.github.io/Docs/Admin-Vibe/#vibe-customization')
102
113
 
103
114
  def read_standard_imports(self) -> List[str]:
104
115
  '''grr
@@ -127,7 +138,6 @@ class GenAIAdminApp:
127
138
  def fix_resource(genai_app: GenAIAdminApp, raw_source: str) -> str:
128
139
  ''' Remove occasional begin/end code markers <br>
129
140
  And horrific override of ChatGPT refusal to generate imports AS DIRECTED!<br>
130
- ToDo: lint, and repeat generation if errors detected
131
141
  '''
132
142
 
133
143
  source_lines = raw_source.splitlines()
@@ -140,13 +150,38 @@ class GenAIAdminApp:
140
150
  continue
141
151
  else:
142
152
  break
143
- if do_mandatory_imports := True and not imports_done and ' props ' in each_line:
153
+ if do_mandatory_imports := True and not imports_done and 'props' in each_line:
144
154
  result_lines = list(genai_app.standard_imports)
145
155
  imports_done = True
146
156
  result_lines.append(each_line)
157
+ parse_result = True
147
158
  # return source_lines as a string
148
159
  return "\n".join(result_lines)
149
160
 
161
+ def js_lint_source_code(target_file: Path):
162
+ # js lint target_file: npx eslint target_file.js
163
+ # needs: eslint
164
+ # needs: npm install eslint-plugin-jsdoc
165
+ # works manually: npx eslint /Users/val/dev/ApiLogicServer/ApiLogicServer-dev/servers/basic_demo/ui/basic_demo_app/src/Customer.js -c .eslintrc.js
166
+ # failing: Value for 'config' of type 'path::String' required.\nYou're using eslint.config.js
167
+ config = self.project.api_logic_server_dir_path / 'tools/.eslintrc.js'
168
+ assert config.exists()
169
+ try:
170
+ result = subprocess.run(
171
+ ["npx", "eslint", str(target_file), '-c ' + str(config)[1:]],
172
+ capture_output=True,
173
+ text=True
174
+ )
175
+ if result.returncode == 0:
176
+ source_code_fixed = True
177
+ else:
178
+ log.warning(f"ESLint issues in {target_file}:\n{result.stdout}\n{result.stderr}")
179
+ source_code_fixed = False
180
+ except Exception as e:
181
+ log.warning(f"Could not lint {target_file}: {e}")
182
+ # If linting fails, assume code is okay to proceed
183
+ source_code_fixed = True
184
+ return source_code_fixed
150
185
 
151
186
  for each_resource_name, each_resource in self.resources.items():
152
187
  learning = self.admin_app_resource_learning
@@ -154,20 +189,33 @@ class GenAIAdminApp:
154
189
  messages = [
155
190
  {"role": "user", "content": "You are a helpful expert in react and JavaScript"},
156
191
  {"role": "user", "content": learning},
157
- # {"role": "user", "content": example_image_content},
158
- # {"role": "user", "content": f'Schema:\n{self.schema_yaml}'},
159
192
  {"role": "user", "content": f'Schema:\n{self.schema}'},
160
193
  {"role": "user", "content": f'Generate the full javascript source code for the `{each_resource_name}.js` React Admin file, formatted as a JSResponseFormat'}]
161
194
  save_response = self.project_root / f"docs/admin_app/{each_resource_name}"
162
- output = genai_svcs.call_chatgpt(messages = messages,
163
- api_version=self.api_version,
164
- using=save_response,
165
- response_as=JSResponseFormat)
166
- response_dict = json.loads(output)
167
- target_file = self.ui_src_path / f"{each_resource_name}.js"
168
- source_code = fix_resource(self, response_dict['code'])
169
- utils.write_file(target_file, source_code)
170
- log.info(f"..✅ Wrote: {each_resource_name}.js")
195
+ retry_number = 0
196
+
197
+ max_retries = 2
198
+ while retry_number <= self.retries: # loop until lint succeeds, max retry_number times
199
+ retry_number += 1
200
+ output = genai_svcs.call_chatgpt(
201
+ messages=messages,
202
+ api_version=self.api_version,
203
+ using=save_response,
204
+ response_as=JSResponseFormat
205
+ )
206
+ response_dict = json.loads(output)
207
+ target_file = self.ui_src_path / f"{each_resource_name}.js"
208
+ source_code = fix_resource(self, response_dict['code'])
209
+ utils.write_file(target_file, source_code)
210
+ source_code_fixed = True
211
+ if self.retries > 1: # 1 retry (current , per setup issues) means no lint
212
+ source_code_fixed = js_lint_source_code(target_file=target_file)
213
+ if source_code_fixed:
214
+ break
215
+ if source_code_fixed:
216
+ log.info(f"..✅ Wrote: {each_resource_name}.js")
217
+ else:
218
+ log.warning(f"..❌ {self.retries} retries did not fix: {each_resource_name}.js")
171
219
 
172
220
 
173
221
  def b_generate_app_js(self):
@@ -0,0 +1,43 @@
1
+ import shutil
2
+ from typing import Dict, List
3
+ from api_logic_server_cli.cli_args_project import Project
4
+ import logging
5
+ from pathlib import Path
6
+ import importlib
7
+ import requests
8
+ import os, time
9
+ import datetime
10
+ import json
11
+ from typing import List, Dict
12
+ from pydantic import BaseModel
13
+ import create_from_model.api_logic_server_utils as create_utils
14
+ import json
15
+
16
+ log = logging.getLogger(__name__)
17
+
18
+
19
+ class JSResponseFormat(BaseModel): # must match system/genai/prompt_inserts/response_format.prompt
20
+ code : str # generated javascript code (only)
21
+
22
+
23
+ class GenMCP:
24
+
25
+ def __init__(self, project: Project, admin_app: bool, api_logic_server_path: Path):
26
+ self.start_time = time.time()
27
+
28
+ self.project_root = project.project_directory_path
29
+
30
+ log.info(f'\ngenai_mcp here..')
31
+
32
+ shutil.copyfile(api_logic_server_path / 'templates/mcp_client_executor_request.py',
33
+ project.project_directory_path / 'logic/logic_discovery/mcp_client_executor_request.py')
34
+
35
+ if admin_app:
36
+ lines = create_utils.read_file(path = api_logic_server_path / 'fragments/mcp_admin.yml')
37
+ admin_yaml_path = project.project_directory_path / 'ui/admin/admin.yaml'
38
+ create_utils.insert_lines_at(lines = lines,
39
+ at = 'settings:',
40
+ file_name = admin_yaml_path)
41
+ pass
42
+ pass
43
+
@@ -966,7 +966,7 @@ def call_chatgpt(messages: List[Dict[str, str]], api_version: str, using: str, r
966
966
  log.error(f"\n\nError: ChatGPT call failed\n- please see https://apilogicserver.github.io/Docs/WebGenAI-CLI/#configuratio\n{inst}\n\n")
967
967
  sys.exit(1)
968
968
 
969
- def get_manager_path(use_env: bool = False) -> Path:
969
+ def get_manager_path(project: object = None) -> Path:
970
970
  """ Checks cwd, parent, and grandparent for system/genai
971
971
 
972
972
  * Possibly could add cli arg later
@@ -978,46 +978,47 @@ def get_manager_path(use_env: bool = False) -> Path:
978
978
  Path: Manager path (contains system/genai)
979
979
  """
980
980
 
981
- if use_env and os.getenv("APILOGICSERVER_HOME") is not None:
982
- result_path = Path(os.getenv("APILOGICSERVER_HOME")).joinpath('api_logic_server_cli/prototypes/manager')
981
+ if project is not None:
982
+ result_path = project.manager_path
983
+ check_system_genai = result_path.joinpath('system/genai/temp')
984
+ if check_system_genai.exists():
985
+ return result_path
983
986
  return result_path
984
987
 
985
988
  result_path = Path(os.getcwd()) # normal case - project at manager root
986
- check_system_genai = result_path.joinpath('system/genai')
989
+ check_system_genai = result_path.joinpath('system/genai/temp')
987
990
  if check_system_genai.exists():
988
991
  return result_path
989
992
 
990
993
  result_path = result_path.parent # try pwd parent
991
- check_system_genai = result_path.joinpath('system/genai')
994
+ check_system_genai = result_path.joinpath('system/genai/temp')
992
995
  if check_system_genai.exists():
993
996
  return result_path
994
997
 
995
998
  result_path = result_path.parent # try pwd grandparent
996
- check_system_genai = result_path.joinpath('system/genai')
999
+ check_system_genai = result_path.joinpath('system/genai/temp')
997
1000
  if check_system_genai.exists():
998
1001
  return result_path
999
1002
 
1000
1003
  result_path = result_path.parent
1001
- check_system_genai = result_path.joinpath('system/genai')
1004
+ check_system_genai = result_path.joinpath('system/genai/temp')
1002
1005
  if check_system_genai.exists():
1003
1006
  return result_path
1004
1007
 
1005
1008
  result_path = result_path.parent
1006
- check_system_genai = result_path.joinpath('system/genai')
1009
+ check_system_genai = result_path.joinpath('system/genai/temp')
1007
1010
  if check_system_genai.exists():
1008
1011
  return result_path
1009
1012
 
1010
1013
  result_path = result_path.parent
1011
- check_system_genai = result_path.joinpath('system/genai')
1014
+ check_system_genai = result_path.joinpath('system/genai/temp')
1012
1015
  if check_system_genai.exists():
1013
1016
  return result_path
1014
1017
 
1015
1018
  result_path = result_path.parent # try ancestors - this is for import testing
1016
- check_system_genai = result_path.joinpath('system/genai')
1019
+ check_system_genai = result_path.joinpath('system/genai/temp')
1017
1020
 
1018
1021
  if not check_system_genai.exists():
1019
- if use_env:
1020
- result_path = Path(create_utils.get_api_logic_server_dir()).joinpath('prototypes/manager')
1021
1022
  check_system_genai.exists(), f"Manager Directory not found and APILOGICSERVER_HOME not set: {check_system_genai}"
1022
1023
  return result_path
1023
1024
 
@@ -31,10 +31,35 @@ def create_manager(clean: bool, open_with: str, api_logic_server_path: Path,
31
31
  clean (bool): Overlay existing manager (projects and web_genai retained)
32
32
  open_with (str): IDE to use
33
33
  api_logic_server_path (Path): _description_
34
- volume (str, optional): _description_. Defaults to "".
34
+ volume (str, optional): for docker. Defaults to "".
35
35
  open_manager (bool, optional): Whether to open IDE at Manager. Defaults to True.
36
+ samples (bool, optional): Whether to create large samples (prevent win max file length)
36
37
  """
37
38
 
39
+ def create_sym_links(cli_path: Path, mgr_path: Path):
40
+ """
41
+ Creates symbolic links to sample dbs and prompts (clearer than db abbreviations).
42
+
43
+ Args:
44
+ cli_path (Path): loc of cli.py in the manager's venv
45
+ mgr_path (Path): path of manager being created
46
+
47
+ Side Effects:
48
+ Creates a symbolic link from 'cli_path/database/basic_demo.sqlite' to 'mgr_path/samples/dbs/basic_demo'.
49
+ Prints a confirmation message upon successful creation.
50
+
51
+ Raises:
52
+ OSError: If the symbolic link cannot be created (e.g., due to permissions or existing link).
53
+ """
54
+
55
+ # create symbolic link - thanks https://www.geeksforgeeks.org/python/python-os-symlink-method/
56
+ try:
57
+ os.symlink(cli_path.parent / 'database/basic_demo.sqlite', mgr_path / 'samples/db/basic_demo.sqlite')
58
+ print("Link created")
59
+ except Exception as e:
60
+ pass
61
+
62
+
38
63
  log = logging.getLogger(__name__)
39
64
 
40
65
  project = PR.ProjectRun(command= "start", project_name='ApiLogicServer', db_url='sqlite', execute=False)
@@ -55,6 +80,7 @@ def create_manager(clean: bool, open_with: str, api_logic_server_path: Path,
55
80
  log.info(f"\nStarting manager at: {os.getcwd()}") # eg, ...ApiLogicServer-dev/clean/ApiLogicServer
56
81
 
57
82
  docker_volume = ''
83
+ ''' normally volume " '/' '''
58
84
  if project.is_docker:
59
85
  # volume typically /ApiLogicServer... % docker run -it --name api_logic_server --rm --net dev-network -p 5656:5656 -p 5002:5002 -v ${PWD}:/ApiLogicServer apilogicserver/api_logic_server
60
86
  if do_local_docker_test == False: # normal path
@@ -161,7 +187,7 @@ def create_manager(clean: bool, open_with: str, api_logic_server_path: Path,
161
187
  codegen_logger.setLevel(codegen_logger_save_level)
162
188
  pass
163
189
 
164
- # find cli in subdirectories of the lib path for manager run launches, and update run/debug config
190
+ # find cli in subdirectories of the lib path for manager run launches, and update `.vscode/launch.json`
165
191
  if manager_exists or project.is_docker:
166
192
  log.debug(f" docker -- not updating .env and launch.json\n\n")
167
193
  else:
@@ -187,6 +213,7 @@ def create_manager(clean: bool, open_with: str, api_logic_server_path: Path,
187
213
  create_utils.replace_string_in_file(search_for = 'cli_path',
188
214
  replace_with=str(cli_str),
189
215
  in_file=vscode_launch_path)
216
+ create_sym_links(cli_path=cli_path, mgr_path=to_dir)
190
217
 
191
218
  if env_path.exists():
192
219
  create_utils.replace_string_in_file(search_for = 'APILOGICSERVER_AUTO_OPEN=code',
@@ -6,6 +6,9 @@ SQLAlCHEMY_ECHO = False
6
6
  # APILOGICPROJECT_KAFKA_PRODUCER = "{\"bootstrap.servers\": \"localhost:9092\"}"
7
7
  # SQLALCHEMY_DATABASE_URI=db.sqlite
8
8
 
9
+ # required if you are not running from venv or docker apilogicserver/api_logic_server (eg, azure)
10
+ # APILOGICPROJECT_APILOGICSERVERHOME=src/ApiLogicServer-src
11
+
9
12
  SECURITY_ENABLED = false
10
13
 
11
14
  # if using tunnel for mcp, function, or ai_plugin
@@ -55,9 +55,9 @@ echo " "
55
55
  if [ ! -f "./database/authentication_models.py" ]
56
56
  then
57
57
  echo "\nYou need to activate security first. With you database running, ...\n"
58
- echo "ApiLogicServer add-auth --project_name=. --db_url=mysql+pymysql://root:p@localhost:3306/authdb, or..."
59
- echo "ApiLogicServer add-auth --project_name=. --db_url=postgresql://postgres:p@localhost/authdb", or...
60
- echo "ApiLogicServer add-auth --project_name=. --db_url=authdb"
58
+ echo "genai-logic add-auth --project_name=. --db_url=mysql+pymysql://root:p@localhost:3306/authdb, or..."
59
+ echo "genai-logic add-auth --project_name=. --db_url=postgresql://postgres:p@localhost/authdb", or...
60
+ echo "genai-logic add-auth --project_name=. --db_url=authdb"
61
61
  echo "\nRebuild your image"
62
62
  echo "\nThen, stop mysql/postgres containers to avoid port conflicts with services\n"
63
63
  exit 1
@@ -21,7 +21,7 @@ pwd
21
21
  if [ ! -f "./../../database/database_discovery/authentication_models.py" ]
22
22
  then
23
23
  echo "\nYou need to activate security first. With mysql-container running...\n"
24
- echo "ApiLogicServer add-auth --project_name=. --db_url=mysql+pymysql://root:p@localhost:3306/authdb"
24
+ echo "genai-logic add-auth --project_name=. --db_url=mysql+pymysql://root:p@localhost:3306/authdb"
25
25
  echo "\nRebuild your image"
26
26
  echo "\nThen, stop mysql-container\n"
27
27
  exit 1