ApiLogicServer 14.3.25__py3-none-any.whl → 14.5.0__py3-none-any.whl

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (167) hide show
  1. api_logic_server_cli/add_cust/add_cust.py +283 -0
  2. api_logic_server_cli/api_logic_server.py +18 -250
  3. api_logic_server_cli/api_logic_server_info.yaml +3 -3
  4. api_logic_server_cli/cli.py +54 -35
  5. api_logic_server_cli/create_from_model/__pycache__/api_logic_server_utils.cpython-312.pyc +0 -0
  6. api_logic_server_cli/create_from_model/__pycache__/create_db_from_model.cpython-312.pyc +0 -0
  7. api_logic_server_cli/create_from_model/__pycache__/dbml.cpython-312.pyc +0 -0
  8. api_logic_server_cli/create_from_model/__pycache__/ont_build.cpython-312.pyc +0 -0
  9. api_logic_server_cli/create_from_model/__pycache__/ont_create.cpython-312.pyc +0 -0
  10. api_logic_server_cli/create_from_model/api_logic_server_utils.py +47 -0
  11. api_logic_server_cli/create_from_model/create_db_from_model.py +2 -0
  12. api_logic_server_cli/create_from_model/dbml.py +113 -58
  13. api_logic_server_cli/create_from_model/ont_build.py +102 -74
  14. api_logic_server_cli/create_from_model/ont_create.py +7 -6
  15. api_logic_server_cli/create_from_model/safrs-react-admin-npm-build/static/.DS_Store +0 -0
  16. api_logic_server_cli/database/basic_demo.sqlite +0 -0
  17. api_logic_server_cli/database/basic_demo.txt +1 -0
  18. api_logic_server_cli/database/basic_demo_wg.sqlite +0 -0
  19. api_logic_server_cli/database/nw-gold-fix.sql +62 -0
  20. api_logic_server_cli/database/nw-gold.sqlite +0 -0
  21. api_logic_server_cli/{prototypes/manager/webgenai → fragments}/docker-compose.yml +1 -1
  22. api_logic_server_cli/genai/genai.py +42 -11
  23. api_logic_server_cli/genai/genai_graphics.py +252 -38
  24. api_logic_server_cli/genai/genai_svcs.py +20 -12
  25. api_logic_server_cli/manager.py +22 -12
  26. api_logic_server_cli/prototypes/.DS_Store +0 -0
  27. api_logic_server_cli/prototypes/base/.DS_Store +0 -0
  28. api_logic_server_cli/prototypes/base/.vscode/launch.json +22 -2
  29. api_logic_server_cli/prototypes/base/api/expose_api_models.py +3 -1
  30. api_logic_server_cli/prototypes/base/api_logic_server_run.py +5 -2
  31. api_logic_server_cli/prototypes/base/config/activate_logicbank.py +1 -0
  32. api_logic_server_cli/prototypes/base/config/config.py +123 -25
  33. api_logic_server_cli/prototypes/base/config/default.env +7 -1
  34. api_logic_server_cli/prototypes/base/config/logging.yml +1 -0
  35. api_logic_server_cli/prototypes/base/config/server_setup.py +33 -1
  36. api_logic_server_cli/prototypes/base/database/test_data/readme.md +5 -2
  37. api_logic_server_cli/prototypes/base/devops/docker-standard-image/docker-compose-standard-image.yml +7 -2
  38. api_logic_server_cli/prototypes/base/docs/training/logic_bank_api.prompt +314 -0
  39. api_logic_server_cli/prototypes/base/docs/training/logic_example.py +41 -0
  40. api_logic_server_cli/prototypes/base/integration/kafka/kafka_producer.py +12 -5
  41. api_logic_server_cli/prototypes/base/integration/n8n/n8n_producer.py +68 -21
  42. api_logic_server_cli/prototypes/base/integration/n8n/n8n_readme.md +19 -0
  43. api_logic_server_cli/prototypes/base/integration/system/FlaskKafka.py +5 -1
  44. api_logic_server_cli/prototypes/base/test/basic/server_test.py +1 -1
  45. api_logic_server_cli/prototypes/base/ui/templates/bar_chart.jinja +64 -0
  46. api_logic_server_cli/prototypes/basic_demo/README.md +29 -52
  47. api_logic_server_cli/prototypes/basic_demo/customizations/api/.DS_Store +0 -0
  48. api_logic_server_cli/prototypes/basic_demo/customizations/api/api_discovery/mcp_server_executor.py +138 -0
  49. api_logic_server_cli/prototypes/basic_demo/customizations/api/api_discovery/openapi.py +92 -0
  50. api_logic_server_cli/prototypes/basic_demo/customizations/api/api_discovery/proper_update_def.json +71 -0
  51. api_logic_server_cli/prototypes/basic_demo/customizations/config/default.env +13 -0
  52. api_logic_server_cli/prototypes/basic_demo/customizations/database/db.sqlite +0 -0
  53. api_logic_server_cli/prototypes/basic_demo/customizations/database/models.py +131 -0
  54. api_logic_server_cli/prototypes/basic_demo/customizations/integration/.DS_Store +0 -0
  55. api_logic_server_cli/prototypes/basic_demo/customizations/integration/mcp/.DS_Store +0 -0
  56. api_logic_server_cli/prototypes/basic_demo/customizations/integration/mcp/1_langchain_loader.py +71 -0
  57. api_logic_server_cli/prototypes/basic_demo/customizations/integration/mcp/2_gpt_mcp_prompt.txt +19 -0
  58. api_logic_server_cli/prototypes/basic_demo/customizations/integration/mcp/README_mcp.md +13 -0
  59. api_logic_server_cli/prototypes/basic_demo/customizations/integration/mcp/mcp_client_executor.py +295 -0
  60. api_logic_server_cli/prototypes/basic_demo/customizations/integration/mcp/mcp_schema.txt +47 -0
  61. api_logic_server_cli/prototypes/basic_demo/customizations/integration/mcp/mcp_server_discovery.json +9 -0
  62. api_logic_server_cli/prototypes/basic_demo/customizations/integration/mcp/multi_mcp_flow/multi_mcp_flow.png +0 -0
  63. api_logic_server_cli/prototypes/basic_demo/customizations/integration/mcp/multi_mcp_flow/multi_mcp_orchestration.yaml +49 -0
  64. api_logic_server_cli/prototypes/basic_demo/customizations/integration/mcp/multi_mcp_flow/wny mcp flows.png +0 -0
  65. api_logic_server_cli/prototypes/basic_demo/customizations/integration/mcp/natlang_to_api.py +73 -0
  66. api_logic_server_cli/prototypes/basic_demo/customizations/integration/mcp/resources/curl.txt +5 -0
  67. api_logic_server_cli/prototypes/basic_demo/customizations/integration/mcp/resources/images/MCP Overview.png +0 -0
  68. api_logic_server_cli/prototypes/basic_demo/customizations/integration/mcp/resources/images/MCP_Arch.png +0 -0
  69. api_logic_server_cli/prototypes/basic_demo/customizations/integration/mcp/resources/images/MCP_Overview_Executor.png +0 -0
  70. api_logic_server_cli/prototypes/basic_demo/customizations/integration/mcp/resources/invoke_llm/1 - prompt_messages_array.json +10 -0
  71. api_logic_server_cli/prototypes/basic_demo/customizations/integration/mcp/resources/invoke_llm/2 - completion_tool_context.json +12 -0
  72. api_logic_server_cli/prototypes/basic_demo/customizations/integration/mcp/resources/llm_schema.txt +38 -0
  73. api_logic_server_cli/prototypes/basic_demo/customizations/integration/mcp/resources/nw_swagger_2.yaml +17393 -0
  74. api_logic_server_cli/prototypes/basic_demo/customizations/integration/mcp/resources/nw_swagger_3.yaml +16660 -0
  75. api_logic_server_cli/prototypes/basic_demo/customizations/integration/mcp/resources/nw_swagger_3_relaxed.yaml +109 -0
  76. api_logic_server_cli/prototypes/basic_demo/customizations/integration/mcp/resources/proxy_server.py +51 -0
  77. api_logic_server_cli/prototypes/basic_demo/customizations/integration/mcp/resources/proxy_serverZ.py +72 -0
  78. api_logic_server_cli/prototypes/basic_demo/customizations/integration/mcp/resources/validate_jsonapi.py +64 -0
  79. api_logic_server_cli/prototypes/basic_demo/customizations/integration/mcp/run_executor.py +23 -0
  80. api_logic_server_cli/prototypes/basic_demo/customizations/integration/mcp/swagger_converter.py +65 -0
  81. api_logic_server_cli/prototypes/basic_demo/customizations/integration/mcp/z_old/3_executor_test_agent.py +52 -0
  82. api_logic_server_cli/prototypes/basic_demo/customizations/integration/openai_function/3_executor_test_agent.py +52 -0
  83. api_logic_server_cli/prototypes/basic_demo/customizations/integration/openai_function/README_functon.md +201 -0
  84. api_logic_server_cli/prototypes/basic_demo/customizations/integration/openai_function/ai_plugin.json +17 -0
  85. api_logic_server_cli/prototypes/basic_demo/customizations/integration/openai_function/nw-swagger_3.json +1731 -0
  86. api_logic_server_cli/prototypes/basic_demo/customizations/integration/openai_function/snippets.txt +5 -0
  87. api_logic_server_cli/prototypes/basic_demo/customizations/integration/openai_function/swagger_3 genai_demo_with_get.json +1731 -0
  88. api_logic_server_cli/prototypes/basic_demo/customizations/integration/openai_function/swagger_3.json +1782 -0
  89. api_logic_server_cli/prototypes/basic_demo/customizations/integration/openai_function/swagger_3_genai_demo.json +264 -0
  90. api_logic_server_cli/prototypes/basic_demo/customizations/integration/openai_function/swagger_3_genai_demo_with_update.json +1782 -0
  91. api_logic_server_cli/prototypes/basic_demo/customizations/logic/declare_logic.py +62 -44
  92. api_logic_server_cli/prototypes/basic_demo/customizations/security/declare_security.py +11 -12
  93. api_logic_server_cli/prototypes/basic_demo/customizations/ui/admin/admin.yaml +166 -0
  94. api_logic_server_cli/prototypes/basic_demo/iteration/api/{customize_api.py → api_discovery/order_b2b.py} +17 -23
  95. api_logic_server_cli/prototypes/basic_demo/iteration/database/db.sqlite +0 -0
  96. api_logic_server_cli/prototypes/basic_demo/iteration/integration/row_dict_maps/OrderB2B.py +6 -5
  97. api_logic_server_cli/prototypes/basic_demo/iteration/integration/row_dict_maps/OrderShipping.py +4 -4
  98. api_logic_server_cli/prototypes/basic_demo/iteration/logic/declare_logic.py +69 -43
  99. api_logic_server_cli/prototypes/basic_demo/iteration/ui/admin/admin.yaml +125 -50
  100. api_logic_server_cli/prototypes/genai_demo/ui/admin/admin.yaml +1 -1
  101. api_logic_server_cli/prototypes/manager/README.md +30 -4
  102. api_logic_server_cli/prototypes/manager/README_X.md +663 -0
  103. api_logic_server_cli/prototypes/manager/system/genai/.DS_Store +0 -0
  104. api_logic_server_cli/prototypes/manager/system/genai/examples/.DS_Store +0 -0
  105. api_logic_server_cli/prototypes/manager/system/genai/examples/genai_demo/.DS_Store +0 -0
  106. api_logic_server_cli/prototypes/manager/system/genai/examples/genai_demo/genai_demo.prompt +0 -10
  107. api_logic_server_cli/prototypes/manager/system/genai/examples/genai_demo/genai_demo.response_example +32 -10
  108. api_logic_server_cli/prototypes/manager/system/genai/examples/genai_demo/genai_demo_docs_logic/docs/002_create_db_models.prompt +4 -4
  109. api_logic_server_cli/prototypes/manager/system/genai/examples/genai_demo/genai_demo_docs_logic/docs/003_create_db_models.response +77 -47
  110. api_logic_server_cli/prototypes/manager/system/genai/examples/genai_demo/genai_demo_informal.prompt +1 -1
  111. api_logic_server_cli/prototypes/manager/system/genai/graphics_templates/dashboard_services.jinja +83 -0
  112. api_logic_server_cli/prototypes/manager/system/genai/graphics_templates/graphics_dashboard_WIP.py +34 -0
  113. api_logic_server_cli/prototypes/manager/system/genai/graphics_templates/{graphics_services.py → graphics_services_api_xxx.py} +0 -9
  114. api_logic_server_cli/prototypes/manager/system/genai/graphics_templates/graphics_services_db.jinja +46 -0
  115. api_logic_server_cli/prototypes/manager/system/genai/graphics_templates/graphics_services_db_each_method.jinja +36 -0
  116. api_logic_server_cli/prototypes/manager/system/genai/prompt_inserts/graphics.prompt +7 -3
  117. api_logic_server_cli/prototypes/manager/system/genai/prompt_inserts/response_format.prompt +8 -1
  118. api_logic_server_cli/prototypes/manager/system/install-ApiLogicServer-dev/install-ApiLogicServer-dev.ps1 +100 -0
  119. api_logic_server_cli/prototypes/manager/system/install-ApiLogicServer-dev/install-ApiLogicServer-dev.sh +116 -0
  120. api_logic_server_cli/prototypes/manager/system/install-ApiLogicServer-dev/readme.md +7 -0
  121. api_logic_server_cli/prototypes/manager/system/style-guide.yaml +2 -2
  122. api_logic_server_cli/prototypes/manager/webgenai/README.md +6 -0
  123. api_logic_server_cli/prototypes/nw/docs/graphics/count_orders_by_category.prompt +1 -0
  124. api_logic_server_cli/prototypes/nw/docs/graphics/order_count_by_month.prompt +1 -0
  125. api_logic_server_cli/prototypes/nw/docs/graphics/request copy.json +892 -0
  126. api_logic_server_cli/prototypes/nw/docs/graphics/request.json +6 -0
  127. api_logic_server_cli/prototypes/nw/docs/graphics/response.json +17 -0
  128. api_logic_server_cli/prototypes/nw/docs/graphics/response.yaml +59 -0
  129. api_logic_server_cli/prototypes/nw/docs/graphics/sales_by_category.prompt +1 -0
  130. api_logic_server_cli/prototypes/nw/ui/admin/home.js +5 -4
  131. api_logic_server_cli/prototypes/nw/ui/app_model_custom.yaml +851 -1082
  132. api_logic_server_cli/prototypes/nw_no_cust/Tutorial.md +45 -26
  133. api_logic_server_cli/prototypes/nw_no_cust/api/api_discovery/openapi.py +130 -0
  134. api_logic_server_cli/prototypes/nw_no_cust/api/api_discovery/proper_update_def.json +71 -0
  135. api_logic_server_cli/prototypes/nw_no_cust/config/default.env +13 -0
  136. api_logic_server_cli/prototypes/nw_no_cust/docs/graphics/count_orders_by_category.prompt +1 -0
  137. api_logic_server_cli/prototypes/nw_no_cust/docs/graphics/sales_by_employee.prompt +1 -0
  138. api_logic_server_cli/prototypes/ont_app/ontimize_seed/nginx/nginx.conf +2 -2
  139. api_logic_server_cli/prototypes/ont_app/ontimize_seed/package-lock.json +9725 -1180
  140. api_logic_server_cli/prototypes/ont_app/ontimize_seed/package.json +6 -9
  141. api_logic_server_cli/prototypes/ont_app/ontimize_seed/src/app/app.config.ts +2 -1
  142. api_logic_server_cli/prototypes/ont_app/ontimize_seed/src/app/shared/app.services.config.ts +1 -1
  143. api_logic_server_cli/prototypes/ont_app/ontimize_seed/src/assets/css/app.scss +4 -0
  144. api_logic_server_cli/prototypes/ont_app/ontimize_seed/src/assets/i18n/en.json +1 -1
  145. api_logic_server_cli/prototypes/ont_app/ontimize_seed/src/assets/i18n/es.json +14 -12
  146. api_logic_server_cli/prototypes/ont_app/ontimize_seed/src/environments/environment.prod.ts +5 -5
  147. api_logic_server_cli/prototypes/ont_app/ontimize_seed/src/environments/environment.ts +5 -5
  148. api_logic_server_cli/prototypes/ont_app/templates/app_config.jinja +1 -1
  149. api_logic_server_cli/prototypes/ont_app/templates/date_template.html +1 -1
  150. api_logic_server_cli/prototypes/ont_app/templates/detail_template.html +1 -1
  151. api_logic_server_cli/prototypes/ont_app/templates/new_template.html +16 -16
  152. api_logic_server_cli/prototypes/ont_app/templates/textarea_template.html +1 -1
  153. api_logic_server_cli/prototypes/ont_app/templates/timestamp_template.html +1 -1
  154. api_logic_server_cli/prototypes/sample_ai/logic/declare_logic.py +30 -13
  155. apilogicserver-14.5.0.dist-info/METADATA +76 -0
  156. {apilogicserver-14.3.25.dist-info → apilogicserver-14.5.0.dist-info}/RECORD +160 -88
  157. {apilogicserver-14.3.25.dist-info → apilogicserver-14.5.0.dist-info}/WHEEL +1 -1
  158. api_logic_server_cli/prototypes/basic_demo/apply_customizations.ps1 +0 -17
  159. api_logic_server_cli/prototypes/basic_demo/apply_customizations.sh +0 -14
  160. api_logic_server_cli/prototypes/basic_demo/apply_iteration.ps1 +0 -20
  161. api_logic_server_cli/prototypes/basic_demo/apply_iteration.sh +0 -15
  162. api_logic_server_cli/prototypes/manager/system/genai/graphics_templates/service_template_jsonapi_rpc.jinja +0 -37
  163. api_logic_server_cli/prototypes/manager/system/genai/graphics_templates/service_template_unused.jinja +0 -38
  164. apilogicserver-14.3.25.dist-info/METADATA +0 -167
  165. {apilogicserver-14.3.25.dist-info → apilogicserver-14.5.0.dist-info}/entry_points.txt +0 -0
  166. {apilogicserver-14.3.25.dist-info → apilogicserver-14.5.0.dist-info}/licenses/LICENSE +0 -0
  167. {apilogicserver-14.3.25.dist-info → apilogicserver-14.5.0.dist-info}/top_level.txt +0 -0
@@ -0,0 +1,109 @@
1
+ openapi: 3.0.3
2
+ info:
3
+ title: Customer API
4
+ version: 1.0.0
5
+ description: API for retrieving customer information, including filtering by country and pagination.
6
+
7
+ servers:
8
+ - url: https://your-ngrok-url.ngrok-free.app/api
9
+
10
+ paths:
11
+ /Customer:
12
+ get:
13
+ summary: List Customers
14
+ description: Retrieve a list of customers, optionally filtering by country, limiting results, and sorting.
15
+ parameters:
16
+ - in: query
17
+ name: filter[Country]
18
+ schema:
19
+ type: string
20
+ description: Filter customers by country name (e.g., Germany).
21
+ - in: query
22
+ name: page[limit]
23
+ schema:
24
+ type: integer
25
+ description: Maximum number of customers to return.
26
+ - in: query
27
+ name: page[offset]
28
+ schema:
29
+ type: integer
30
+ description: Number of customers to skip before starting to collect results.
31
+ - in: query
32
+ name: sort
33
+ schema:
34
+ type: string
35
+ description: Field to sort by (e.g., id).
36
+ responses:
37
+ '200':
38
+ description: A list of customers
39
+ content:
40
+ application/json:
41
+ schema:
42
+ type: object
43
+ properties:
44
+ data:
45
+ type: array
46
+ items:
47
+ type: object
48
+ properties:
49
+ id:
50
+ type: string
51
+ description: Customer ID
52
+ type:
53
+ type: string
54
+ example: Customer
55
+ attributes:
56
+ type: object
57
+ properties:
58
+ CompanyName:
59
+ type: string
60
+ ContactName:
61
+ type: string
62
+ ContactTitle:
63
+ type: string
64
+ Address:
65
+ type: string
66
+ City:
67
+ type: string
68
+ Region:
69
+ type: string
70
+ PostalCode:
71
+ type: string
72
+ Country:
73
+ type: string
74
+ Phone:
75
+ type: string
76
+ Fax:
77
+ type: string
78
+ Balance:
79
+ type: number
80
+ CreditLimit:
81
+ type: number
82
+ OrderCount:
83
+ type: integer
84
+ UnpaidOrderCount:
85
+ type: integer
86
+ Client_id:
87
+ type: integer
88
+ S_CheckSum:
89
+ type: string
90
+ meta:
91
+ type: object
92
+ properties:
93
+ count:
94
+ type: integer
95
+ limit:
96
+ type: integer
97
+ total:
98
+ type: integer
99
+ links:
100
+ type: object
101
+ properties:
102
+ self:
103
+ type: string
104
+ next:
105
+ type: string
106
+ last:
107
+ type: string
108
+
109
+ components: {}
@@ -0,0 +1,51 @@
1
+ from flask import Flask, request, make_response
2
+ import requests
3
+ import json
4
+
5
+ app = Flask(__name__)
6
+
7
+ @app.route('/api/Customer')
8
+ def proxy_customer():
9
+ # The real API endpoint
10
+ real_url = 'https://your-real-server.ngrok-free.app/api/Customer'
11
+
12
+ try:
13
+ # Fetch from the actual API
14
+ response = requests.get(real_url, params=request.args, headers={'Accept': 'application/json'})
15
+ response.raise_for_status()
16
+ real_data = response.json()
17
+
18
+ transformed_data = {
19
+ "data": [],
20
+ "jsonapi": {"version": "1.0"},
21
+ "links": {"self": request.url}
22
+ }
23
+
24
+ # Convert each customer to JSON:API format
25
+ for item in real_data.get("data", []):
26
+ attributes = item.get("attributes", {})
27
+ attributes.pop("Id", None) # Remove duplicate ID if present
28
+
29
+ transformed_data["data"].append({
30
+ "type": "Customer",
31
+ "id": item.get("id") or attributes.get("Id"),
32
+ "attributes": attributes
33
+ })
34
+
35
+ # JSON:API-compliant response
36
+ response_json = json.dumps(transformed_data)
37
+ response_obj = make_response(response_json)
38
+ response_obj.headers["Content-Type"] = "application/vnd.api+json"
39
+ return response_obj
40
+
41
+ except Exception as e:
42
+ error_response = {"errors": [{"title": "Proxy Error", "detail": str(e)}]}
43
+ response_json = json.dumps(error_response)
44
+ response_obj = make_response(response_json, 500)
45
+ response_obj.headers["Content-Type"] = "application/vnd.api+json"
46
+ return response_obj
47
+
48
+ if __name__ == '__main__':
49
+ app.run(host='0.0.0.0', port=6000, debug=True)
50
+
51
+ # test: curl "http://localhost:6000/api/Customer?filter%5BCountry%5D=Germany&page%5Blimit%5D=2"
@@ -0,0 +1,72 @@
1
+ # Step 1: Install Flask and Requests libraries
2
+ # Run this once: pip install flask requests
3
+
4
+ import json
5
+ from flask import Flask, jsonify, request
6
+ from flask import make_response
7
+ import requests
8
+
9
+ app = Flask(__name__)
10
+
11
+ @app.before_request
12
+ def before_any_request():
13
+ print(f"[DEBUG] Incoming request: {request.method} {request.url}")
14
+
15
+ # Step 2: Proxy endpoint to fix /api/Customer
16
+ @app.route('/api/Customer')
17
+ def proxy_customer():
18
+ import pprint
19
+ real_url = 'https://your-ngrok-url.ngrok-free.app/api/Customer'
20
+ real_url = 'http://localhost:5656/api/Customer'
21
+
22
+ try:
23
+ print(f"[Proxy] Forwarding to: {real_url}")
24
+ print(f"[Proxy] With params: {request.args}")
25
+
26
+ response = requests.get(real_url, params=request.args, headers={'Accept': 'application/json'})
27
+ response.raise_for_status()
28
+ real_data = response.json()
29
+
30
+ print("[Proxy] Got response:")
31
+ pprint.pprint(real_data)
32
+
33
+ transformed_data = {
34
+ "data": []
35
+ }
36
+
37
+ transformed_data = {
38
+ "data": [
39
+ {
40
+ "type": "Customer",
41
+ "id": attributes.get("Id"),
42
+ "attributes": attributes
43
+ } for item in real_data.get("data", [])
44
+ if (attributes := item.get("attributes"))
45
+ ]
46
+ }
47
+
48
+ for item in real_data.get("data", []):
49
+ attributes = item.get("attributes", {})
50
+ attributes.pop("Id", None) # Remove duplicate ID TODO
51
+ transformed_data["data"].append({
52
+ "type": "Customer",
53
+ "id": item.get("id") or attributes.get("Id"),
54
+ "attributes": attributes
55
+ })
56
+
57
+
58
+ response_json = json.dumps(transformed_data)
59
+ response_obj = make_response(response_json)
60
+ response_obj.headers["Content-Type"] = "application/vnd.api+json"
61
+ return response_obj
62
+ except Exception as e:
63
+ print("[Proxy] ERROR:", e)
64
+ return jsonify({"error": str(e)}), 500
65
+
66
+ # Run the proxy locally
67
+ if __name__ == '__main__':
68
+ app.run(host='0.0.0.0', port=6000, debug=True)
69
+
70
+ # test:
71
+ # http://localhost:6000/api/Customer
72
+ # curl "http://localhost:6000/api/Customer?filter%5BCountry%5D=Germany&page%5Blimit%5D=2"
@@ -0,0 +1,64 @@
1
+ import requests
2
+
3
+ def validate_jsonapi_response(url):
4
+ try:
5
+ response = requests.get(
6
+ url,
7
+ headers={"Accept": "application/vnd.api+json"},
8
+ timeout=10
9
+ )
10
+
11
+ validation_report = {
12
+ "status_code": response.status_code,
13
+ "content_type_correct": False,
14
+ "top_level_keys_valid": False,
15
+ "resource_objects_valid": False,
16
+ "errors": []
17
+ }
18
+
19
+ # Check Content-Type header
20
+ content_type = response.headers.get('Content-Type', '')
21
+ if "application/vnd.api+json" in content_type:
22
+ validation_report["content_type_correct"] = True
23
+ else:
24
+ validation_report["errors"].append("Incorrect Content-Type: expected 'application/vnd.api+json'.")
25
+
26
+ # Check top-level keys
27
+ json_body = response.json()
28
+ if any(k in json_body for k in ["data", "errors", "meta"]):
29
+ validation_report["top_level_keys_valid"] = True
30
+ else:
31
+ validation_report["errors"].append("Missing required top-level key: data, errors, or meta.")
32
+
33
+ # If data is present, validate resource objects
34
+ if "data" in json_body:
35
+ data = json_body["data"]
36
+ if isinstance(data, list):
37
+ resources = data
38
+ else:
39
+ resources = [data]
40
+
41
+ all_resources_valid = True
42
+ for res in resources:
43
+ if not all(key in res for key in ["id", "type", "attributes"]):
44
+ all_resources_valid = False
45
+ validation_report["errors"].append(
46
+ f"Invalid resource object: missing id, type, or attributes -> {res}"
47
+ )
48
+ break
49
+ validation_report["resource_objects_valid"] = all_resources_valid
50
+
51
+ except Exception as e:
52
+ validation_report = {
53
+ "error": str(e)
54
+ }
55
+
56
+ return validation_report
57
+
58
+ # Example: Replace with your actual URL
59
+ test_url = "https://dcba-2601-644-4900-d6f0-806d-b9f7-9f64-7677.ngrok-free.app/api/Customer"
60
+
61
+ # Run validator
62
+ result = validate_jsonapi_response(test_url)
63
+ print(result)
64
+ # {'status_code': 200, 'content_type_correct': True, 'top_level_keys_valid': True, 'resource_objects_valid': True, 'errors': []}
@@ -0,0 +1,23 @@
1
+ import requests
2
+
3
+ tool_context = {
4
+ "method": "GET",
5
+ "url": "http://localhost:5656/api/Customer",
6
+ "query_params": {
7
+ "filter[Country]": "Germany",
8
+ "page[limit]": 2
9
+ },
10
+ "headers": {
11
+ "Accept": "application/vnd.api+json"
12
+ }
13
+ }
14
+
15
+ response = requests.get(
16
+ tool_context["url"],
17
+ headers=tool_context["headers"],
18
+ params=tool_context["query_params"]
19
+ )
20
+
21
+ print(f"Status Code: {response.status_code}")
22
+ print("Response JSON:")
23
+ print(response.json())
@@ -0,0 +1,65 @@
1
+ import yaml
2
+ import subprocess
3
+ import tempfile
4
+ import os
5
+ '''
6
+ convert swagger 2.0 to openapi 3.0
7
+ pip install pyyaml
8
+ npm install -g swagger2openapi
9
+ '''
10
+ def filter_swagger(input_file, output_file, include_paths_methods):
11
+ """
12
+ include_paths_methods: dict of {"/path": ["get", "post", ...]}
13
+ """
14
+ with open(input_file, 'r') as f:
15
+ swagger = yaml.safe_load(f)
16
+
17
+ filtered_paths = {}
18
+ tags = []
19
+ for path, methods in swagger.get('paths', {}).items():
20
+ if path in include_paths_methods:
21
+ print(f"Filtering path: {path}")
22
+ tags.append({"name": path.replace("/", "",2)})
23
+ filtered_methods = {
24
+ method: op
25
+ for method, op in methods.items()
26
+ if method.lower() in [m.lower() for m in include_paths_methods[path]]
27
+ }
28
+ if filtered_methods:
29
+ print
30
+ filtered_paths[path] = filtered_methods
31
+ swagger['tags'] = tags
32
+ swagger['paths'] = filtered_paths
33
+ info ={}
34
+ swagger["info"]['termsOfService'] = 'http://genai-logic.com/terms'
35
+
36
+ # Save filtered swagger to a temporary file
37
+ with tempfile.NamedTemporaryFile(delete=False, mode='w', suffix='.yaml') as tmp:
38
+ yaml.dump(swagger, tmp)
39
+ tmp_input_file = tmp.name
40
+
41
+ # Call swagger2openapi to convert to OpenAPI 3
42
+
43
+ subprocess.run([
44
+ 'swagger2openapi',
45
+ tmp_input_file,
46
+ '-o', output_file,
47
+ '--yaml',
48
+ ], check=True)
49
+
50
+ os.remove(tmp_input_file)
51
+ print(f"Converted OpenAPI 3.0 spec written to: {output_file}")
52
+
53
+
54
+ # Example usage
55
+ if __name__ == "__main__":
56
+
57
+ input_swagger_file = 'api_logic_server_cli/prototypes/nw_no_cust/integration/mcp/resources/nw_swagger_2.yaml'
58
+ output_openapi_file = 'api_logic_server_cli/prototypes/nw_no_cust/integration/mcp/resources/openapi_3.yaml'
59
+ # Choose which paths and methods to include
60
+ include = {
61
+ "/Customer/": ["get", "post"],
62
+ "/Order/": ["get"]
63
+ }
64
+
65
+ filter_swagger(input_swagger_file, output_openapi_file, include)
@@ -0,0 +1,52 @@
1
+ import requests, json
2
+
3
+ # MCP-style tool_context
4
+ # does not like this pagination
5
+ tool_context = {
6
+ "method": "GET",
7
+ "url": "http://localhost:5656/api/Customer",
8
+ "query_params": {
9
+ "filter[Country]": "Germany",
10
+ "page[limit]": 2
11
+ },
12
+ "headers": {
13
+ "Accept": "application/vnd.api+json"
14
+ }
15
+ }
16
+
17
+ tool_context = { # use this for nw
18
+ "method": "GET",
19
+ "url": "http://localhost:5656/api/Customer",
20
+ "query_params": {
21
+ "filter[Country]": "Germany"
22
+ },
23
+ "headers": {
24
+ "Accept": "application/vnd.api+json"
25
+ , "Authorization": "Bearer your_token"
26
+ }
27
+ }
28
+
29
+ tool_context = { # use this for genai_demo
30
+ "method": "GET",
31
+ "url": "http://localhost:5656/api/Customer",
32
+ "query_params": {
33
+ "filter[name]": "Alice"
34
+ },
35
+ "headers": {
36
+ "Accept": "application/vnd.api+json"
37
+ , "Authorization": "Bearer your_token"
38
+ }
39
+ }
40
+
41
+ # Execute as a simulated MCP executor
42
+ response = requests.get( # use this for genai_demo
43
+ tool_context["url"],
44
+ headers=tool_context["headers"],
45
+ params=tool_context["query_params"]
46
+ )
47
+
48
+ # Display result
49
+ print(response.status_code)
50
+ # Print the response, format it as JSON with indent
51
+ print(json.dumps(response.json(), indent=4))
52
+
@@ -0,0 +1,52 @@
1
+ import requests, json
2
+
3
+ # MCP-style tool_context
4
+ # does not like this pagination
5
+ tool_context = {
6
+ "method": "GET",
7
+ "url": "http://localhost:5656/api/Customer",
8
+ "query_params": {
9
+ "filter[Country]": "Germany",
10
+ "page[limit]": 2
11
+ },
12
+ "headers": {
13
+ "Accept": "application/vnd.api+json"
14
+ }
15
+ }
16
+
17
+ tool_context = { # use this for nw
18
+ "method": "GET",
19
+ "url": "http://localhost:5656/api/Customer",
20
+ "query_params": {
21
+ "filter[Country]": "Germany"
22
+ },
23
+ "headers": {
24
+ "Accept": "application/vnd.api+json"
25
+ , "Authorization": "Bearer your_token"
26
+ }
27
+ }
28
+
29
+ tool_context = { # use this for genai_demo
30
+ "method": "GET",
31
+ "url": "http://localhost:5656/api/Customer",
32
+ "query_params": {
33
+ "filter[name]": "Alice"
34
+ },
35
+ "headers": {
36
+ "Accept": "application/vnd.api+json"
37
+ , "Authorization": "Bearer your_token"
38
+ }
39
+ }
40
+
41
+ # Execute as a simulated MCP executor
42
+ response = requests.get( # use this for genai_demo
43
+ tool_context["url"],
44
+ headers=tool_context["headers"],
45
+ params=tool_context["query_params"]
46
+ )
47
+
48
+ # Display result
49
+ print(response.status_code)
50
+ # Print the response, format it as JSON with indent
51
+ print(json.dumps(response.json(), indent=4))
52
+
@@ -0,0 +1,201 @@
1
+ **OpenAI functions** are tools that extend the capabilities of ChatGPT by allowing it to access real-time data, perform actions, or connect with external services via APIs. .
2
+
3
+ Instead of being limited to its pre-trained knowledge, ChatGPT can use plugins to retrieve up-to-date information (like live weather, stock prices, or databases) or perform tasks (like booking a flight or running a query).
4
+
5
+ The goal is to turn ChatGPT into a more useful, interactive assistant that can bridge AI language understanding with real-world actions and live data.
6
+
7
+ >For example, in large companies, it can be remarkably hard to find corporate systems via an Intranet, and use different user interfaces. ChatGPT can simplify finding these, and interacting with Natural Language.
8
+
9
+ This is to explore:
10
+
11
+ | Explore | Status |
12
+ | ------------------------------------------ | -------------------- |
13
+ | Nat Lang ALS Access using OpenAI Functions | Initial Test Running |
14
+ | | |
15
+
16
+ A value prop might be summarized: *instantly expose legacy DBs to Natural Language, including critical business logic and security, to simplify user discovery and operation.*
17
+
18
+ <br>
19
+
20
+ ## Status: Technology Exploration
21
+
22
+ This is an initial experiment, without automation. Many substantive issues need to be addressed, including but not limited to security, update, etc.
23
+
24
+ We welcome participation in this exploration. Please contact us via [discord](https://discord.gg/HcGxbBsgRF).
25
+
26
+ This exploration is changing rapidly. For updates, replace `integration/mcp` from [integration/msp](https://github.com/ApiLogicServer/ApiLogicServer-src/tree/main/api_logic_server_cli/prototypes/nw_no_cust/integration/openai_plugin)
27
+
28
+ <br>
29
+
30
+ ## Nat Lang ALS Access using OpenAI Plugin
31
+
32
+ Requires tunnel to local host such as [ngrok](https://ngrok.com/downloads/mac-os?tab=download), then
33
+
34
+ ```
35
+ ngrok config add-authtoken <obtain from https://dashboard.ngrok.com/get-started/setup/macos>
36
+ ```
37
+
38
+ then start the tunnel
39
+
40
+ ```
41
+ ngrok http 5656
42
+ ```
43
+
44
+ You should see:
45
+
46
+ ![ngrok](https://github.com/ApiLogicServer/Docs/blob/main/docs/images/integration/mcp/ngrok.png?raw=true)
47
+
48
+ and note the url like: `https://42da-2601-644-4900-etc.ngrok-free.app -> http://localhost:5656`
49
+
50
+ We'll call it `tunnel_url`
51
+
52
+ Enter this into `config/default.env`
53
+
54
+ <br>
55
+
56
+ ### Use GenAI_Demo
57
+
58
+ See `mcp/README_mcp.md`
59
+
60
+ <br>
61
+
62
+ ### Obtain swagger_3
63
+
64
+ This has already been done using the procedure described below.
65
+
66
+ Obtain swagger 2 from API Logic Server, eg, http://localhost:5656/api/swagger.json)
67
+
68
+ Convert to 3: https://converter.swagger.io or other.
69
+
70
+ <br>
71
+
72
+ #### Reduce to 30 Operations
73
+
74
+ Reduce down to 30 operations (genai_demo has 69).
75
+
76
+ For testing, you can copy `integration/openai_plugin/swagger_3_genai_demo.json` or `integration/openai_plugin/nw-swagger_3.json` over `integration/openai_plugin/swagger_3.json`.
77
+
78
+ This was obtained using ChatGPT with prompts like:
79
+
80
+ 1. Optionally collapse GET by ID and GET collection into a single endpoint using query params
81
+ 2. remove POST from relationship endpoints
82
+ 3. remove delete
83
+ 4. collapse relationship endpoints further
84
+
85
+ then fix the result:
86
+
87
+ 1. ensure servers and paths is retained (got deleted for me), and includes https:
88
+ 2. version 3.1.0
89
+
90
+ Still seeing (fix with Chat):
91
+
92
+ ```
93
+ In path /Customer, method get is missing operationId; skipping
94
+ In path /Customer, method post is missing operationId; skipping
95
+ In path /Order, method get is missing operationId; skipping
96
+ In path /Order, method post is missing operationId; skipping
97
+ In path /Item, method get is missing operationId; skipping
98
+ In path /Item, method post is missing operationId; skipping
99
+ In path /Product, method get is missing operationId; skipping
100
+ In path /Product, method post is missing operationId; skipping
101
+ ```
102
+
103
+ <br>
104
+
105
+ ### Custom endpoint for openapi
106
+
107
+ OpenAI requires a openai document, so observe the custom endpoint - `api/api_discovery/openapi` - eg, to test locally: `http://localhost:5656/api/openai.json`
108
+
109
+ Note: the url for use in ChatGPT is the tunnelled version, from the env variable.
110
+
111
+ <br>
112
+
113
+ ### Configure in ChatGPT
114
+
115
+ Then, upload it to the **Web** version of ChatGPT:
116
+
117
+ 1. Explore GPTs
118
+ 2. Create
119
+ 3. Configure
120
+ 4. Create New Action
121
+
122
+ Provide the url of the openai endpoint:
123
+
124
+ https://tunnel_url.ngrok-free.app/api/openapi.json
125
+
126
+ <br>
127
+
128
+ ### Retrieval worked:
129
+
130
+ - list customers
131
+ - list the items of order 1 with their product names
132
+
133
+ <br>
134
+
135
+ ### Update: Resoved, pending verification
136
+
137
+ We also experimented with update, using `integration/openai_plugin/swagger_3.json`.
138
+
139
+ > It initially failed to load, which we repaired as noted in Appendix 2.
140
+
141
+ > It then failed to generate proper update API, evidently due to bad OpenAPI spec as noted in Appendix 3.
142
+
143
+ <br>
144
+
145
+ ## Appendices
146
+
147
+ <br>
148
+
149
+ ### Appendix 1: Create ai_plug_in.json
150
+
151
+ We also looked at openai plugins. These appear to be discontinued.
152
+
153
+ Prepare `ai_plug_in.json` as shown in this directory. Observe that it It identifies the url for finding the openapi through the tunnel.
154
+
155
+ Note: both ALS and and `ai_plug_in.json` presume the swagger and api are consistent:
156
+
157
+ - swagger is at `http://localhost:5656/api/swagger.json`,
158
+ - typical API at `http://localhost:5656/api/Category`
159
+
160
+ Not required for function - **Settings / Beta / Plugins > Plugin install → expects the ai-plugin.json manifest URL**
161
+
162
+ This appears to be unavailable for ChatGPT 4o
163
+
164
+ <br>
165
+
166
+ ### Appendix 2: Updateable openapi
167
+
168
+ It initially failed to load with
169
+
170
+ ```
171
+ In context=('paths', '/Customer/{CustomerId}/', 'patch', 'requestBody', 'content', 'application/json', 'schema'), reference to unknown component Customer_inst; using empty schema
172
+
173
+ In path /Customer/{CustomerId}/, method patch, operationId UpdateCustomer_0, request body schema is not an object schema; skipping
174
+
175
+ In path /Customer/{CustomerId}/, method patch, operationId UpdateCustomer_0, skipping function due to errors
176
+ ```
177
+
178
+ We requested a revised jasonapi from ChatGPT to clear these errors, which loaded.
179
+
180
+ <br>
181
+
182
+ ### Appendix 3: Invalid Data Object
183
+
184
+ This appears to be caused by improper JSON:API openAPI spec, which caused ChatGPT to generate an improper json PATCH payload:
185
+
186
+ ```python
187
+ chatgpt_request_json = {
188
+ "credit_limit": 25000,
189
+ }
190
+ standard_request_json = {
191
+ "data": {
192
+ "type": "Customer",
193
+ "id": "ALFKI",
194
+ "attributes": {
195
+ "name": "Alice",
196
+ "credit_limit": 25000,
197
+ "balance": 12345
198
+ }
199
+ }
200
+ }
201
+ ```