pyxecm 2.0.4__py3-none-any.whl → 3.0.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.

Potentially problematic release.


This version of pyxecm might be problematic. Click here for more details.

Files changed (94) hide show
  1. pyxecm/coreshare.py +5 -3
  2. pyxecm/helper/data.py +4 -4
  3. pyxecm/helper/otel_config.py +26 -0
  4. pyxecm/helper/web.py +1 -2
  5. pyxecm/otca.py +1356 -16
  6. pyxecm/otcs.py +2354 -593
  7. pyxecm/otds.py +1 -1
  8. pyxecm/otmm.py +4 -5
  9. pyxecm/py.typed +0 -0
  10. pyxecm-3.0.0.dist-info/METADATA +48 -0
  11. pyxecm-3.0.0.dist-info/RECORD +96 -0
  12. {pyxecm-2.0.4.dist-info → pyxecm-3.0.0.dist-info}/WHEEL +1 -2
  13. pyxecm-3.0.0.dist-info/entry_points.txt +4 -0
  14. {pyxecm/customizer/api → pyxecm_api}/__main__.py +1 -1
  15. pyxecm_api/agents/__init__.py +7 -0
  16. pyxecm_api/agents/app.py +13 -0
  17. pyxecm_api/agents/functions.py +119 -0
  18. pyxecm_api/agents/models.py +10 -0
  19. pyxecm_api/agents/otcm_knowledgegraph/functions.py +85 -0
  20. pyxecm_api/agents/otcm_knowledgegraph/models.py +61 -0
  21. pyxecm_api/agents/otcm_knowledgegraph/router.py +74 -0
  22. pyxecm_api/agents/otcm_user_agent/models.py +20 -0
  23. pyxecm_api/agents/otcm_user_agent/router.py +65 -0
  24. pyxecm_api/agents/otcm_workspace_agent/models.py +40 -0
  25. pyxecm_api/agents/otcm_workspace_agent/router.py +200 -0
  26. pyxecm_api/app.py +221 -0
  27. {pyxecm/customizer/api → pyxecm_api}/auth/functions.py +10 -2
  28. {pyxecm/customizer/api → pyxecm_api}/auth/router.py +4 -3
  29. {pyxecm/customizer/api → pyxecm_api}/common/functions.py +39 -9
  30. {pyxecm/customizer/api → pyxecm_api}/common/metrics.py +1 -2
  31. {pyxecm/customizer/api → pyxecm_api}/common/router.py +7 -8
  32. {pyxecm/customizer/api → pyxecm_api}/settings.py +21 -6
  33. {pyxecm/customizer/api → pyxecm_api}/terminal/router.py +1 -1
  34. {pyxecm/customizer/api → pyxecm_api}/v1_csai/router.py +39 -10
  35. pyxecm_api/v1_csai/statics/bindings/utils.js +189 -0
  36. pyxecm_api/v1_csai/statics/tom-select/tom-select.complete.min.js +356 -0
  37. pyxecm_api/v1_csai/statics/tom-select/tom-select.css +334 -0
  38. pyxecm_api/v1_csai/statics/vis-9.1.2/vis-network.css +1 -0
  39. pyxecm_api/v1_csai/statics/vis-9.1.2/vis-network.min.js +27 -0
  40. pyxecm_api/v1_maintenance/__init__.py +1 -0
  41. {pyxecm/customizer/api → pyxecm_api}/v1_maintenance/functions.py +3 -3
  42. {pyxecm/customizer/api → pyxecm_api}/v1_maintenance/router.py +8 -8
  43. pyxecm_api/v1_otcs/__init__.py +1 -0
  44. {pyxecm/customizer/api → pyxecm_api}/v1_otcs/functions.py +7 -5
  45. {pyxecm/customizer/api → pyxecm_api}/v1_otcs/router.py +8 -7
  46. pyxecm_api/v1_payload/__init__.py +1 -0
  47. {pyxecm/customizer/api → pyxecm_api}/v1_payload/functions.py +10 -7
  48. {pyxecm/customizer/api → pyxecm_api}/v1_payload/router.py +11 -10
  49. {pyxecm/customizer → pyxecm_customizer}/__init__.py +8 -0
  50. {pyxecm/customizer → pyxecm_customizer}/__main__.py +15 -21
  51. {pyxecm/customizer → pyxecm_customizer}/browser_automation.py +414 -103
  52. {pyxecm/customizer → pyxecm_customizer}/customizer.py +178 -116
  53. {pyxecm/customizer → pyxecm_customizer}/guidewire.py +60 -20
  54. {pyxecm/customizer → pyxecm_customizer}/k8s.py +4 -4
  55. pyxecm_customizer/knowledge_graph.py +719 -0
  56. pyxecm_customizer/log.py +35 -0
  57. {pyxecm/customizer → pyxecm_customizer}/m365.py +41 -33
  58. {pyxecm/customizer → pyxecm_customizer}/payload.py +2265 -1933
  59. {pyxecm/customizer/api/common → pyxecm_customizer}/payload_list.py +18 -55
  60. {pyxecm/customizer → pyxecm_customizer}/salesforce.py +1 -1
  61. {pyxecm/customizer → pyxecm_customizer}/sap.py +6 -2
  62. {pyxecm/customizer → pyxecm_customizer}/servicenow.py +2 -4
  63. {pyxecm/customizer → pyxecm_customizer}/settings.py +7 -6
  64. {pyxecm/customizer → pyxecm_customizer}/successfactors.py +40 -28
  65. {pyxecm/customizer → pyxecm_customizer}/translate.py +1 -1
  66. {pyxecm/maintenance_page → pyxecm_maintenance_page}/__main__.py +1 -1
  67. {pyxecm/maintenance_page → pyxecm_maintenance_page}/app.py +14 -8
  68. pyxecm/customizer/api/app.py +0 -157
  69. pyxecm/customizer/log.py +0 -107
  70. pyxecm/customizer/nhc.py +0 -1169
  71. pyxecm/customizer/openapi.py +0 -258
  72. pyxecm/customizer/pht.py +0 -1357
  73. pyxecm-2.0.4.dist-info/METADATA +0 -119
  74. pyxecm-2.0.4.dist-info/RECORD +0 -78
  75. pyxecm-2.0.4.dist-info/licenses/LICENSE +0 -202
  76. pyxecm-2.0.4.dist-info/top_level.txt +0 -1
  77. {pyxecm/customizer/api → pyxecm_api}/__init__.py +0 -0
  78. {pyxecm/customizer/api/auth → pyxecm_api/agents/otcm_knowledgegraph}/__init__.py +0 -0
  79. {pyxecm/customizer/api/common → pyxecm_api/agents/otcm_user_agent}/__init__.py +0 -0
  80. {pyxecm/customizer/api/v1_csai → pyxecm_api/agents/otcm_workspace_agent}/__init__.py +0 -0
  81. {pyxecm/customizer/api/v1_maintenance → pyxecm_api/auth}/__init__.py +0 -0
  82. {pyxecm/customizer/api → pyxecm_api}/auth/models.py +0 -0
  83. {pyxecm/customizer/api/v1_otcs → pyxecm_api/common}/__init__.py +0 -0
  84. {pyxecm/customizer/api → pyxecm_api}/common/models.py +0 -0
  85. {pyxecm/customizer/api → pyxecm_api}/terminal/__init__.py +0 -0
  86. {pyxecm/customizer/api/v1_payload → pyxecm_api/v1_csai}/__init__.py +0 -0
  87. {pyxecm/customizer/api → pyxecm_api}/v1_csai/models.py +0 -0
  88. {pyxecm/customizer/api → pyxecm_api}/v1_maintenance/models.py +0 -0
  89. {pyxecm/customizer/api → pyxecm_api}/v1_payload/models.py +0 -0
  90. {pyxecm/customizer → pyxecm_customizer}/exceptions.py +0 -0
  91. {pyxecm/maintenance_page → pyxecm_maintenance_page}/__init__.py +0 -0
  92. {pyxecm/maintenance_page → pyxecm_maintenance_page}/settings.py +0 -0
  93. {pyxecm/maintenance_page → pyxecm_maintenance_page}/static/favicon.avif +0 -0
  94. {pyxecm/maintenance_page → pyxecm_maintenance_page}/templates/maintenance.html +0 -0
pyxecm/otds.py CHANGED
@@ -2220,7 +2220,7 @@ class OTDS:
2220
2220
  name (str):
2221
2221
  The name of the OTDS resource to update.
2222
2222
  resource (object):
2223
- updated resource object of get_resource called before
2223
+ The updated resource object of get_resource called before
2224
2224
  show_error (bool, optional):
2225
2225
  If True, log an error if resource is not found. Else just log a warning.
2226
2226
 
pyxecm/otmm.py CHANGED
@@ -19,7 +19,7 @@ import threading
19
19
  import traceback
20
20
  import urllib.parse
21
21
  from collections.abc import Callable
22
- from datetime import datetime, timezone
22
+ from datetime import UTC, datetime
23
23
  from importlib.metadata import version
24
24
  from json import JSONDecodeError
25
25
 
@@ -884,11 +884,11 @@ class OTMM:
884
884
  try:
885
885
  if os.path.exists(file_name):
886
886
  if asset_modification_date:
887
- file_mod_time = datetime.fromtimestamp(os.path.getmtime(file_name), tz=timezone.utc)
887
+ file_mod_time = datetime.fromtimestamp(os.path.getmtime(file_name), tz=UTC)
888
888
  date_last_updated = datetime.strptime(
889
889
  asset_modification_date,
890
890
  "%Y-%m-%dT%H:%M:%SZ",
891
- ).replace(tzinfo=timezone.utc)
891
+ ).replace(tzinfo=UTC)
892
892
  download_up_to_date: bool = file_mod_time >= date_last_updated
893
893
  else:
894
894
  download_up_to_date = True
@@ -927,8 +927,7 @@ class OTMM:
927
927
  response = self._session.get(request_url, stream=True)
928
928
  response.raise_for_status()
929
929
  with open(file_name, "wb") as f:
930
- for chunk in response.iter_content(chunk_size=8192):
931
- f.write(chunk)
930
+ f.writelines(response.iter_content(chunk_size=8192))
932
931
  success = True
933
932
  # end try:
934
933
 
pyxecm/py.typed ADDED
File without changes
@@ -0,0 +1,48 @@
1
+ Metadata-Version: 2.4
2
+ Name: pyxecm
3
+ Version: 3.0.0
4
+ Summary: A Python library to interact with Opentext Content Management Rest API
5
+ Project-URL: Homepage, https://github.com/opentext/pyxecm
6
+ Author-email: Kai Gatzweiler <kgatzweiler@opentext.com>, "Dr. Marc Diefenbruch" <mdiefenb@opentext.com>
7
+ Keywords: appworks,archivecenter,contentserver,extendedecm,opentext,otds
8
+ Classifier: Development Status :: 4 - Beta
9
+ Classifier: Intended Audience :: Developers
10
+ Classifier: License :: OSI Approved :: Apache Software License
11
+ Classifier: Operating System :: OS Independent
12
+ Classifier: Programming Language :: Python :: 3
13
+ Classifier: Topic :: Internet :: WWW/HTTP :: Dynamic Content :: Content Management System
14
+ Requires-Python: >=3.10
15
+ Requires-Dist: lxml>=6.0.0
16
+ Requires-Dist: opentelemetry-api>=1.34.1
17
+ Requires-Dist: opentelemetry-exporter-otlp>=1.34.1
18
+ Requires-Dist: opentelemetry-instrumentation-requests>=0.55b1
19
+ Requires-Dist: opentelemetry-instrumentation-threading>=0.55b1
20
+ Requires-Dist: opentelemetry-sdk>=1.34.1
21
+ Requires-Dist: pandas>=2.3.1
22
+ Requires-Dist: requests-toolbelt>=1.0.0
23
+ Requires-Dist: requests>=2.32.4
24
+ Requires-Dist: suds>=1.2.0
25
+ Requires-Dist: websockets>=15.0.1
26
+ Requires-Dist: xmltodict>=0.14.2
27
+ Provides-Extra: api
28
+ Requires-Dist: asyncio>=3.4.3; extra == 'api'
29
+ Requires-Dist: fastapi>=0.116.0; extra == 'api'
30
+ Requires-Dist: jinja2>=3.1.6; extra == 'api'
31
+ Requires-Dist: opentelemetry-api>=1.34.1; extra == 'api'
32
+ Requires-Dist: opentelemetry-instrumentation-fastapi>=0.55b1; extra == 'api'
33
+ Requires-Dist: opentelemetry-sdk>=1.34.1; extra == 'api'
34
+ Requires-Dist: prometheus-fastapi-instrumentator>=7.1.0; extra == 'api'
35
+ Requires-Dist: pydantic-settings>=2.10.1; extra == 'api'
36
+ Requires-Dist: python-multipart>=0.0.20; extra == 'api'
37
+ Requires-Dist: uvicorn>=0.35.0; extra == 'api'
38
+ Provides-Extra: customizer
39
+ Requires-Dist: kubernetes>=33.1.0; extra == 'customizer'
40
+ Requires-Dist: playwright>=1.53.0; extra == 'customizer'
41
+ Requires-Dist: pydantic>=2.11.7; extra == 'customizer'
42
+ Requires-Dist: python-hcl2>=7.2.1; extra == 'customizer'
43
+ Provides-Extra: magic
44
+ Requires-Dist: python-magic; extra == 'magic'
45
+ Provides-Extra: pyvis
46
+ Requires-Dist: pyvis>=0.3.2; extra == 'pyvis'
47
+ Provides-Extra: sap
48
+ Requires-Dist: pyrfc==3.3.1; extra == 'sap'
@@ -0,0 +1,96 @@
1
+ pyxecm/__init__.py,sha256=KNvTFbDVHylf8Ub28osm5Dw0W-ck-94y27lIBuE32RE,441
2
+ pyxecm/avts.py,sha256=J-W7JYrYv7JSI9whZ5iCHtim6vNrTZCXa1oizUWIc0Y,56952
3
+ pyxecm/coreshare.py,sha256=nV3JmWbxnjZP2SyJzVwJnrC_hdn4lwAYPZ-XMtuumjM,95885
4
+ pyxecm/otac.py,sha256=gXoZc-mkI1XoR_mPmDy3up58C1mTYf76rOaSsC4xOHg,22847
5
+ pyxecm/otawp.py,sha256=JA4LGvbqRvXxc7-7pE1YSLO5JxI3rr9rJdMmuUItrNM,112890
6
+ pyxecm/otca.py,sha256=Jtc4rlgI2g1cfqOiclM5qQdwBN-UAq31VP-2SYGZ4MU,71410
7
+ pyxecm/otcs.py,sha256=qby8ctrgYyTKscoi-S6bJp_n8oNdu8Vi33tdJx7QX44,761951
8
+ pyxecm/otds.py,sha256=oDXG3m_YJrJnMKVuL8i57i1eC5iH2Tzkm-xcNo2N-NY,184222
9
+ pyxecm/otiv.py,sha256=I5lt4sz7TN3W7BCstCKQY2WQnei-t0tXdM4QjRQRmWI,2358
10
+ pyxecm/otkd.py,sha256=JMpUa99vtTK7PfCnMJjt6lUyK6C6Aq1i1zjMROI9cvQ,47480
11
+ pyxecm/otmm.py,sha256=OIzhbk6cTtiQMK9z_CQW8orOZNA690WASqyD2OGn1hw,80731
12
+ pyxecm/otpd.py,sha256=6rfCoO5Jm6pETCyp6aKYNTyvI1z44wP76zS-qRotyVk,14831
13
+ pyxecm/py.typed,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
14
+ pyxecm/helper/__init__.py,sha256=B35HdIZC9wZ1m_sx4NOPggyFFJoXmFuA1T2tuPDU1W8,246
15
+ pyxecm/helper/assoc.py,sha256=yOh4GFZEkTfIaVVrHBr4bhMtIv-E76oDVWGqaUdVqyA,7321
16
+ pyxecm/helper/data.py,sha256=nC0m7-3hpsVKGamKqz1J62jnhDy1GpphIciduMkyMMI,123315
17
+ pyxecm/helper/logadapter.py,sha256=ExrIKpA2JKegkTIky0wDDTgPYSvVmwQLrDh5jko_6hQ,724
18
+ pyxecm/helper/otel_config.py,sha256=nMzNi3Jv2_kmYG4thzDpN95bqjy6MbRfV6nlpIZ6SjQ,907
19
+ pyxecm/helper/web.py,sha256=6kPfs6ZFNAOCly3B4qq_lWJMmiNfTrtQrkjl86WLatc,13345
20
+ pyxecm/helper/xml.py,sha256=QhavLKGl_lwSasq1LF05ftj0OIVr04lyNE3bTqtemiA,45641
21
+ pyxecm_api/__init__.py,sha256=8oXxEEFSu2afpyQURpxMA2qTZAB3MUdbBrndogDn5Oc,92
22
+ pyxecm_api/__main__.py,sha256=Q2tcaoSExPMUwGVBrE4AHT8DNvB4XIgwoN4EPDx5Rt8,117
23
+ pyxecm_api/app.py,sha256=xqNLjnCxi2WwZge3klqMgM6-Mf4ZBrdfn1R26icWx04,7074
24
+ pyxecm_api/settings.py,sha256=7hHVxFdK8P8Xy3VF5f-RbbBvTNrJKLTJQZNrGbjNiHQ,5814
25
+ pyxecm_api/agents/__init__.py,sha256=oLpLHN1f7ixqBXdSXaD-4-byeRJaHwpsZ06wIIVgImM,344
26
+ pyxecm_api/agents/app.py,sha256=a_IrajL7oIykFInRNSl5CaUTROcLNiaY3Z71VELJTGY,387
27
+ pyxecm_api/agents/functions.py,sha256=CtNrkrpBKgldcq8HEjNp-8NA_07OvIso3zsunwDzJPo,3665
28
+ pyxecm_api/agents/models.py,sha256=IjLHOt63c9DwtzhaTtQqF-09KXPim-3TmsjfhTh8x3M,218
29
+ pyxecm_api/agents/otcm_knowledgegraph/__init__.py,sha256=ranS8DEliiC4Mlo-bVva9Maj5q08I0I6NJflUFIvOvw,19
30
+ pyxecm_api/agents/otcm_knowledgegraph/functions.py,sha256=Mk4u_z54j0lpEgPxAyCanNm0cwQy8Ay8sh1Bp7i_7jQ,3301
31
+ pyxecm_api/agents/otcm_knowledgegraph/models.py,sha256=EL2rXOU3CVXLoQVkhK0iMIY9vxRJj017BAwsf6e4fNo,2858
32
+ pyxecm_api/agents/otcm_knowledgegraph/router.py,sha256=4-Th2G3E1a_jC5hNvIaiPmBA8uYXsaOAfyL1K3AJfvs,3005
33
+ pyxecm_api/agents/otcm_user_agent/__init__.py,sha256=ranS8DEliiC4Mlo-bVva9Maj5q08I0I6NJflUFIvOvw,19
34
+ pyxecm_api/agents/otcm_user_agent/models.py,sha256=uFIU_6cZhWlruRKThsQEgDQGVRRBr7xYAAVfMoNMiyw,844
35
+ pyxecm_api/agents/otcm_user_agent/router.py,sha256=6gEWXtiKM4d4hnVaTmbNXaTplcJOnjDRFz-CDN4enec,2454
36
+ pyxecm_api/agents/otcm_workspace_agent/__init__.py,sha256=ranS8DEliiC4Mlo-bVva9Maj5q08I0I6NJflUFIvOvw,19
37
+ pyxecm_api/agents/otcm_workspace_agent/models.py,sha256=Sd70syKPGn0Z-q0AQN9NpqaUgO4h6yQ22sUim9Glgl4,1594
38
+ pyxecm_api/agents/otcm_workspace_agent/router.py,sha256=xLkf4D_k_vsbtdQcrcd6AQpMjERrYS2Pavoy8scJaYo,7457
39
+ pyxecm_api/auth/__init__.py,sha256=ranS8DEliiC4Mlo-bVva9Maj5q08I0I6NJflUFIvOvw,19
40
+ pyxecm_api/auth/functions.py,sha256=O15QieJo_lJnviTUcnNs1vNcJGSh2DQdGcUjt-S_Vj8,3336
41
+ pyxecm_api/auth/models.py,sha256=lKebaIHbALZ10quCCKQ3wf7w8V6k84tFXcPV1zbQsS0,271
42
+ pyxecm_api/auth/router.py,sha256=cLWMupxPtuc4wtWJ80jAsbNBte31m5CeZgClN_TMuPs,2165
43
+ pyxecm_api/common/__init__.py,sha256=ranS8DEliiC4Mlo-bVva9Maj5q08I0I6NJflUFIvOvw,19
44
+ pyxecm_api/common/functions.py,sha256=fvgJsyqYi6QDHRL1TF6pJHNfrOG-HuqvxoGSC8N-xMk,3485
45
+ pyxecm_api/common/metrics.py,sha256=kOJ1DZveZJ7xFd1pB12Zbkq6Z-evaTivpgO_ujVbsxM,2707
46
+ pyxecm_api/common/models.py,sha256=c76ysWUt40A875DirsFMXttxwjHvBYvjuOVEXePSZ9k,456
47
+ pyxecm_api/common/router.py,sha256=BXi3SMvkswCIftoVkJIP_Wx8gd3WKJsE3rq6Pult50I,3482
48
+ pyxecm_api/terminal/__init__.py,sha256=RHlTzdGeOY0_dvvNZS_wq6uJcY1OatIUHwCxAUwklaE,43
49
+ pyxecm_api/terminal/router.py,sha256=aler89EUj-d9RDukn-cTKmiogS4Xn0u_mlJBXlGfIUQ,3581
50
+ pyxecm_api/v1_csai/__init__.py,sha256=ranS8DEliiC4Mlo-bVva9Maj5q08I0I6NJflUFIvOvw,19
51
+ pyxecm_api/v1_csai/models.py,sha256=c0VEJP09jsTW83dpHtZnooNvg3SZNuyMHEBCgWQDJ1s,489
52
+ pyxecm_api/v1_csai/router.py,sha256=nN16b5cCDab9tgijFcCehHpHp1aHLZXSLslATrc6vhE,4586
53
+ pyxecm_api/v1_csai/statics/bindings/utils.js,sha256=MRPHMxfDDJnqr7x4KRYWDOfSMYOhSGFdoElmQ-lWDLA,6311
54
+ pyxecm_api/v1_csai/statics/tom-select/tom-select.complete.min.js,sha256=f2dQEyWhXp7M5o3MsmgS6zJ_Gq4pXFxSxSTsYrPxPc0,44776
55
+ pyxecm_api/v1_csai/statics/tom-select/tom-select.css,sha256=JgqUGftl29aF9fEJ-ObePYuXmhVAUK-Tp2GiLTTt54Q,9328
56
+ pyxecm_api/v1_csai/statics/vis-9.1.2/vis-network.css,sha256=LoLURa1YeOqIFlJHDOYyYB-PVfG5nm6-zf-GFGAObQ4,220163
57
+ pyxecm_api/v1_csai/statics/vis-9.1.2/vis-network.min.js,sha256=HyDwc28yy5vt-PY4OyXP6i-Dnhq-gNboBAtNW-o3jGk,468813
58
+ pyxecm_api/v1_maintenance/__init__.py,sha256=ranS8DEliiC4Mlo-bVva9Maj5q08I0I6NJflUFIvOvw,19
59
+ pyxecm_api/v1_maintenance/functions.py,sha256=NDU08aHzPi7KXxKMA4KPHwc-LkpiqqwZU7Wif8yjaJk,3001
60
+ pyxecm_api/v1_maintenance/models.py,sha256=HcrhBg9hhRZg4Y6xuus9T8SCNIsL8ZxX1uuaRrBnFBw,271
61
+ pyxecm_api/v1_maintenance/router.py,sha256=gL_f_-9Slq7yzzOO1uS1aB8N3GduKnm1__7b6cSH7VI,2238
62
+ pyxecm_api/v1_otcs/__init__.py,sha256=ranS8DEliiC4Mlo-bVva9Maj5q08I0I6NJflUFIvOvw,19
63
+ pyxecm_api/v1_otcs/functions.py,sha256=YKC4b6nVtlnBGcu2WqSRLmS3faXagkAokrBMXUblkJE,2012
64
+ pyxecm_api/v1_otcs/router.py,sha256=VCtGmObA2TVJREwx4mA047SzSpsJlfxhRXA6DdlppZw,7055
65
+ pyxecm_api/v1_payload/__init__.py,sha256=ranS8DEliiC4Mlo-bVva9Maj5q08I0I6NJflUFIvOvw,19
66
+ pyxecm_api/v1_payload/functions.py,sha256=xA06ACS4NWUut0FXfrw6Ww-R94y43PVSESyEiZEhKAA,6295
67
+ pyxecm_api/v1_payload/models.py,sha256=eD9A2K23L_cGhBDTO1FGVGJMQ1COaYWmcr-ELE66tOA,1006
68
+ pyxecm_api/v1_payload/router.py,sha256=2twiLBeNNDGIEQ6SCZwLFgd8oYOzgbskS-Q3OL-lKe4,15441
69
+ pyxecm_customizer/__init__.py,sha256=x2NhDlNcubRC-jXzqT02j9kQGXBo36QAehjmcQuSbXw,721
70
+ pyxecm_customizer/__main__.py,sha256=QGQlJJAdLmJccArwPT8XEhBOMSJ-Z8gwLrtHPNfL8Ps,1407
71
+ pyxecm_customizer/browser_automation.py,sha256=2mlj3MxbRFKHgckCml7MZkHWjFno6cej-6YE88_bVV0,67309
72
+ pyxecm_customizer/customizer.py,sha256=9sR2xzJMDx_We3jejt3qMDbUJQTx93LsuTuC3FbTdTE,84059
73
+ pyxecm_customizer/exceptions.py,sha256=YXX0in-UGXfJb6Fei01JQetOtAHqUiITb49OTSaZRkE,909
74
+ pyxecm_customizer/guidewire.py,sha256=YMWb7GQINhHDOfRI33O_aHQ7KVkFwJnnyfgf-oR7RH4,51599
75
+ pyxecm_customizer/k8s.py,sha256=w35Y1h9xuSFwZ3yuL9mBWWnXxI9GEDneBYl8bkaZ70o,56164
76
+ pyxecm_customizer/knowledge_graph.py,sha256=Hsg-z4vusOae4ei8OiZIkeoneD0EvgfL_uKN50eLFSM,30169
77
+ pyxecm_customizer/log.py,sha256=2DmGF3b-ZIOAJCPSmZmxGD7BNxY4-mZm0H_X0HeJedE,916
78
+ pyxecm_customizer/m365.py,sha256=NKtWRFDwVHEQ1nU_LxxKvn2kvZQO7OuXr3A09xQWlBQ,213778
79
+ pyxecm_customizer/payload.py,sha256=x2GjS8ukgHeXE8Qvuc_1f9cWya0AYeQ6zqqrS3Pm28w,1339959
80
+ pyxecm_customizer/payload_list.py,sha256=jCBqDX0g0cH6lPwgJ22M8TwzOq_D9fGani3RgfZrUvs,28153
81
+ pyxecm_customizer/salesforce.py,sha256=rAcjqGJxy-NTWqvm9pV-tYWJD4CEV0Y4g9lI0VZTaS4,63518
82
+ pyxecm_customizer/sap.py,sha256=lD_riOZhYjbZ0_pUZyqhxP6guzBM__TcUjZhSgDowoE,6506
83
+ pyxecm_customizer/servicenow.py,sha256=krgv_LJKX56_WF1Wx62EUeUWwBaVjdcHFxcnyBbDoCI,65333
84
+ pyxecm_customizer/settings.py,sha256=RG3Jhn5pLN1ooESolGX70371Bgw8VB9NHJaADfjtqpk,21219
85
+ pyxecm_customizer/successfactors.py,sha256=DINciC07L2xx6SDQnZYN5SxNzCx7P0F-Yv3GYOFH2o4,38657
86
+ pyxecm_customizer/translate.py,sha256=8ZoCFMN7_cpT6_JVaNL33xTLWREFt36YWj9mYAS8YyQ,4958
87
+ pyxecm_maintenance_page/__init__.py,sha256=09to4a8rygOIN6Z1SCN9tLtW1qPUC78Z-scDbpt0E-Q,136
88
+ pyxecm_maintenance_page/__main__.py,sha256=N_0tw2upUPQZhTYCaIr75LogyaEsp-mlZCon-lIyaxM,158
89
+ pyxecm_maintenance_page/app.py,sha256=pTOeZfgPPq6BT7P8naUjW-ZT9dXqwX6DWazIVL-9Fkc,1997
90
+ pyxecm_maintenance_page/settings.py,sha256=VRReZeNdza7i7lgnQ3wVojzoPDGXZnzr5rsMJY1EnHk,955
91
+ pyxecm_maintenance_page/static/favicon.avif,sha256=POuuPXKbjHVP3BjNLpFIx8MfkQg5z2LZA7sK6lejARg,1543
92
+ pyxecm_maintenance_page/templates/maintenance.html,sha256=0OAinv7jmj3Aa7GNCIoBLDGEMW1-_HdJfwWmkmb6Cs4,5581
93
+ pyxecm-3.0.0.dist-info/METADATA,sha256=3uq-NrrqgoEj56ACyRlWMOpvC8LDfYWAGYwD8jlQ3y0,2239
94
+ pyxecm-3.0.0.dist-info/WHEEL,sha256=qtCwoSJWgHk21S1Kb4ihdzI2rlJ1ZKaIurTj_ngOhyQ,87
95
+ pyxecm-3.0.0.dist-info/entry_points.txt,sha256=prc1mDdpd3bQk98VRBozI363mDUgSwDibDKXGNqKqgI,151
96
+ pyxecm-3.0.0.dist-info/RECORD,,
@@ -1,5 +1,4 @@
1
1
  Wheel-Version: 1.0
2
- Generator: setuptools (80.9.0)
2
+ Generator: hatchling 1.27.0
3
3
  Root-Is-Purelib: true
4
4
  Tag: py3-none-any
5
-
@@ -0,0 +1,4 @@
1
+ [console_scripts]
2
+ pyxecm-api = pyxecm_api:run_api
3
+ pyxecm-customizer = pyxecm_customizer:main
4
+ pyxecm-maintenance-page = pyxecm_maintenance_page:run_api
@@ -1,6 +1,6 @@
1
1
  """Wrapper to start the Customizer API."""
2
2
 
3
- from pyxecm.customizer.api import run_api
3
+ from pyxecm_api import run_api
4
4
 
5
5
  if __name__ == "__main__":
6
6
  run_api()
@@ -0,0 +1,7 @@
1
+ """init Module."""
2
+
3
+ from .otcm_knowledgegraph.router import router as otcm_knowledgegraph_router
4
+ from .otcm_user_agent.router import router as otcm_user_agent_router
5
+ from .otcm_workspace_agent.router import router as otcm_workspace_agent_router
6
+
7
+ __all__ = ["otcm_knowledgegraph_router", "otcm_user_agent_router", "otcm_workspace_agent_router"]
@@ -0,0 +1,13 @@
1
+ """List of all routers for the csai agents."""
2
+
3
+ import logging
4
+
5
+ from fastapi import APIRouter
6
+
7
+ from . import otcm_knowledgegraph_router, otcm_user_agent_router, otcm_workspace_agent_router
8
+
9
+ logger = logging.getLogger("pyxecm_api.agents")
10
+
11
+ router = APIRouter(tags=["csai agents"])
12
+
13
+ agent_routers = [router, otcm_workspace_agent_router, otcm_user_agent_router, otcm_knowledgegraph_router]
@@ -0,0 +1,119 @@
1
+ """List of all routers for the csai agents."""
2
+
3
+ import logging
4
+ from importlib.metadata import version
5
+ from threading import Thread
6
+
7
+ from fastapi.openapi.utils import get_openapi
8
+ from fastapi.routing import APIRoute
9
+ from pyxecm import OTCA, OTCS
10
+ from pyxecm_customizer.settings import Settings
11
+
12
+ from pyxecm_api.common.functions import get_k8s_object, get_otcs_object
13
+
14
+ logger = logging.getLogger("pyxecm_api.agents")
15
+
16
+ SETTINGS = Settings()
17
+
18
+
19
+ def get_otca_object(otcs_object: OTCS | None = None) -> OTCA:
20
+ """Get the OTCA object."""
21
+
22
+ k8s_object = get_k8s_object()
23
+ content_system = {}
24
+ for service in ["chat", "embed"]:
25
+ cm = k8s_object.get_config_map(f"csai-{service}-svc")
26
+ if cm:
27
+ content_system[service] = cm.data.get("CONTENT_SYSTEM", "none")
28
+
29
+ otca = OTCA(
30
+ chat_url=str(SETTINGS.aviator.chat_svc_url),
31
+ embed_url=str(SETTINGS.aviator.embed_svc_url),
32
+ studio_url=str(SETTINGS.aviator.studio_url),
33
+ otds_url=str(SETTINGS.otds.url_internal),
34
+ client_id=SETTINGS.aviator.oauth_client,
35
+ client_secret=SETTINGS.aviator.oauth_secret,
36
+ otcs_object=otcs_object,
37
+ content_system=content_system,
38
+ logger=logger.getChild("otca"),
39
+ )
40
+
41
+ return otca
42
+
43
+
44
+ # end function
45
+
46
+
47
+ def register_tool_body(route: APIRoute, agents: list[str] | None = None) -> dict:
48
+ """Generate the request body for the CSAI Studio integration.
49
+
50
+ Args:
51
+ route (APIRoute):
52
+ The API routes.
53
+ agents (list[str] | None, optional):
54
+ A list of agents this tool is associated with.
55
+ Defaults to ["retrieverAgent"].
56
+
57
+ Returns:
58
+ dict:
59
+ The body for the REST API call to register a tool in Content Aviator.
60
+
61
+ """
62
+
63
+ if agents is None:
64
+ agents = ["retrieverAgent"]
65
+
66
+ return {
67
+ "name": route.name,
68
+ "description": route.description,
69
+ "APISchema": get_openapi(
70
+ title=route.name,
71
+ openapi_version="3.0.0",
72
+ version=version("pyxecm"),
73
+ servers=[{"url": "http://customizer:8000"}],
74
+ routes=[route],
75
+ ),
76
+ "requestTemplate": {
77
+ "data": {"context": {"where": "memory.input.where", "query": "memory.input.query"}},
78
+ },
79
+ "responseTemplate": {}, # Optional response template used to filter the response from the API.
80
+ "agents": agents,
81
+ }
82
+
83
+
84
+ # end function
85
+
86
+
87
+ def register_all() -> None:
88
+ """Register all tools."""
89
+
90
+ def register_all_routes() -> None:
91
+ otca = get_otca_object(otcs_object=get_otcs_object())
92
+ response = otca.do_request(
93
+ method="POST",
94
+ url=str(SETTINGS.aviator.studio_url) + "studio/v1/import",
95
+ show_error=False,
96
+ parse_request_response=False,
97
+ )
98
+ if not response or response.text != "Accepted":
99
+ logger.error("Failed to import tools!")
100
+ return
101
+ get_k8s_object().restart_deployment(deployment_name="csai-chat-svc")
102
+
103
+ for route in routes:
104
+ logger.info("Registering Content Aviator tool -> '%s'...", route.name)
105
+ request_body = register_tool_body(route=route)
106
+ result = otca.register_tool(request_body=request_body)
107
+ if result:
108
+ logger.info("Tool got registered successfully -> %s", route.name)
109
+ logger.debug("%s", result)
110
+
111
+ from pyxecm_api.app import app
112
+
113
+ # Get all FastAPI routes and register them as tools:
114
+ routes: list[APIRoute] = [route for route in app.routes if route.path.startswith("/agents")]
115
+
116
+ Thread(target=register_all_routes, name="RegisterTools").start()
117
+
118
+
119
+ # end function
@@ -0,0 +1,10 @@
1
+ """Define commonly used models."""
2
+
3
+ from pydantic import BaseModel
4
+
5
+
6
+ class Context(BaseModel):
7
+ """Define Model that is used to provide static context information for tools."""
8
+
9
+ where: list[dict]
10
+ query: str
@@ -0,0 +1,85 @@
1
+ """Function to build a knowledge graph from the OTCS object."""
2
+
3
+ import logging
4
+ import time
5
+ from datetime import UTC, datetime
6
+
7
+ from pyxecm_customizer.knowledge_graph import KnowledgeGraph
8
+
9
+ from pyxecm_api.common.functions import get_otcs_object
10
+
11
+ logger = logging.getLogger("pyxecm_api.agent.otcm_knowledge_graph")
12
+
13
+ KNOWLEDGEGRAPH_OBJECT: KnowledgeGraph = None
14
+ KNOWLEDGEGRAPH_ONTOLOGY = {
15
+ ("Vendor", "Material", "child"): ["offers", "supplies", "provides"],
16
+ ("Vendor", "Purchase Order", "child"): ["supplies", "provides"],
17
+ ("Vendor", "Purchase Contract", "child"): ["signs", "owns"],
18
+ ("Material", "Vendor", "parent"): ["is supplied by"],
19
+ ("Purchase Order", "Material", "child"): ["includes", "is part of"],
20
+ ("Customer", "Sales Order", "child"): ["has ordered"],
21
+ ("Customer", "Sales Contract", "child"): ["signs", "owns"],
22
+ ("Sales Order", "Customer", "parent"): ["belongs to", "is initiated by"],
23
+ ("Sales Order", "Material", "child"): ["includes", "consists of"],
24
+ ("Sales Order", "Delivery", "child"): ["triggers", "is followed by"],
25
+ ("Sales Order", "Production Order", "child"): ["triggers", "is followed by"],
26
+ ("Sales Contract", "Material", "child"): ["includes", "consists of"],
27
+ ("Production Order", "Material", "child"): ["includes", "consists of"],
28
+ ("Production Order", "Delivery", "child"): ["triggers", "is followed by"],
29
+ ("Production Order", "Goods Movement", "child"): ["triggers", "is followed by"],
30
+ ("Delivery", "Goods Movement", "child"): ["triggers", "is followed by"],
31
+ ("Delivery", "Material", "child"): ["triggers", "is followed by"],
32
+ }
33
+
34
+
35
+ def build_graph() -> None:
36
+ """Build the knowledgeGraph. And keep it updated every hour."""
37
+
38
+ def build() -> None:
39
+ knowledge_graph = KnowledgeGraph(otcs_object=get_otcs_object(), ontology=KNOWLEDGEGRAPH_ONTOLOGY)
40
+
41
+ start_time = datetime.now(UTC)
42
+ result = knowledge_graph.build_graph(
43
+ workspace_type_exclusions=None,
44
+ workspace_type_inclusions=[
45
+ "Vendor",
46
+ "Purchase Contract",
47
+ "Purchase Order",
48
+ "Material",
49
+ "Customer",
50
+ "Sales Order",
51
+ "Sales Contract",
52
+ "Delivery",
53
+ "Goods Movement",
54
+ ],
55
+ workers=20,
56
+ filter_at_traversal=True, # also filter for workspace types if following relationships
57
+ relationship_types=["child"], # only go from parent to child
58
+ strategy="BFS",
59
+ metadata=False,
60
+ )
61
+ end_time = datetime.now(UTC)
62
+ logger.info(
63
+ "Knowledge Graph completed in %s. Processed %d workspace nodes and traversed %d workspace relationships.",
64
+ str(end_time - start_time),
65
+ result["processed"],
66
+ result["traversed"],
67
+ )
68
+
69
+ global KNOWLEDGEGRAPH_OBJECT # noqa: PLW0603
70
+ KNOWLEDGEGRAPH_OBJECT = knowledge_graph
71
+
72
+ while True:
73
+ logger.info("Building knowledge graph...")
74
+ build()
75
+ logger.info("Knowledge graph build complete. Waiting for 1 hour before rebuilding...")
76
+ time.sleep(3600)
77
+
78
+
79
+ ###
80
+
81
+
82
+ def get_knowledgegraph_object() -> KnowledgeGraph:
83
+ """Get the OTCA object."""
84
+
85
+ return KNOWLEDGEGRAPH_OBJECT
@@ -0,0 +1,61 @@
1
+ """Define Models for KnowledgeGraph."""
2
+
3
+ from typing import Annotated, Literal
4
+
5
+ from pydantic import BaseModel, Field
6
+
7
+ from pyxecm_api.agents.models import Context
8
+ from pyxecm_api.agents.otcm_workspace_agent.models import WorkspaceModel
9
+
10
+
11
+ class KnowledgeGraphQueryModel(BaseModel):
12
+ """Defines Model for describing workspaces in OTCM (Opentext Content Management).
13
+
14
+ To display an instance of this model, please display the link.
15
+ """
16
+
17
+ source_type: Annotated[
18
+ str,
19
+ Field(
20
+ description="Source workspace type name provided in the user query. This provides the start point of the query in the Knowledge Graph."
21
+ ),
22
+ ]
23
+ source_value: Annotated[
24
+ str,
25
+ Field(
26
+ description="Name of the source workspace instance (of the type provided by source_type). This is NOT optional. If it is missing then you need to switch source and target. The source always needs to have a specific value!"
27
+ ),
28
+ ]
29
+ target_type: Annotated[
30
+ str,
31
+ Field(
32
+ description="Target workspace type name provided in the user query. This defines the result workspace types of the Knolwedge Graph query."
33
+ ),
34
+ ] = None
35
+ target_value: Annotated[
36
+ str,
37
+ Field(
38
+ description="Name of the target workspace instance (of the type provided by the target_type). This value is optionalis an additional / optional selection criteria."
39
+ ),
40
+ ] = None
41
+ intermediate_types: Annotated[
42
+ list[str],
43
+ Field(
44
+ description="List of workspace types (entities) that are on the path between the source workspace type and target workspace type. These are typically additional relational conditions the user is giving in the query. The start type and target types should never be in intermediate types!"
45
+ ),
46
+ ] = None
47
+ direction: Annotated[
48
+ Literal["child", "parent"],
49
+ Field(
50
+ description="The direction the graph should be traversed in. This is either 'child' (the default) or 'parent'. 'child' is typically used if traversing from main entities to related sub-entities thus following a '1 -> many' relationship (top-down). 'parent' is typically used if traversing bottom-up. This should reflect the relationship between the source type of the workspace and the requested target type. A 'child' relationship is e.g. 'Customer' -> 'Sales Order'. A 'parent' relationship is e.g. 'Material' -> 'Sales Order'."
51
+ ),
52
+ ] = None
53
+
54
+
55
+ class KnowledgeGraphResponseModel(BaseModel):
56
+ """Response of the Knowledge Graph tool."""
57
+
58
+ results: Annotated[list[WorkspaceModel], Field(description="A list of workspaces matching the query.")]
59
+ context_update: Annotated[
60
+ Context, Field(description="An update for the LLM context. Update the graph state with this information!")
61
+ ]
@@ -0,0 +1,74 @@
1
+ """Define router for workspace endpoints."""
2
+
3
+ import logging
4
+ from typing import Annotated
5
+
6
+ from fastapi import APIRouter, Body, Depends, HTTPException
7
+ from pyxecm_customizer.knowledge_graph import KnowledgeGraph
8
+
9
+ from pyxecm_api.agents.models import Context
10
+ from pyxecm_api.agents.otcm_workspace_agent.models import WorkspaceModel
11
+
12
+ from .functions import (
13
+ KNOWLEDGEGRAPH_ONTOLOGY,
14
+ get_knowledgegraph_object,
15
+ )
16
+ from .models import (
17
+ KnowledgeGraphQueryModel,
18
+ )
19
+
20
+ router = APIRouter(prefix="/otcm_knowledgegraph_agent", tags=["csai agents"])
21
+
22
+ logger = logging.getLogger("pyxecm_api.agents.otcm_knowledgegraph_agent")
23
+
24
+
25
+ @router.post(
26
+ path="/query",
27
+ summary="Query the knowledge graph for a list of workspaces matching the user query.",
28
+ description=f"Use the following ontology to understand the relationship between workspace types and the direction of the relationships (either 'parent' or 'child'): {KNOWLEDGEGRAPH_ONTOLOGY}",
29
+ responses={
30
+ 200: {"description": "Workspaces found"},
31
+ 403: {"description": "Invalid credentials"},
32
+ 404: {"description": "No matching workspaces found"},
33
+ 500: {"description": "Knowledge Graph is not available"},
34
+ },
35
+ # response_model=ToolResponse,
36
+ # response_model=list[WorkspaceModel],
37
+ response_description="List of workspaces that match the query. Best presented as a list with hyperlinks to the workspace.",
38
+ )
39
+ def otcm_knowledgegraph_query(
40
+ context: Context,
41
+ knowledge_graph: Annotated[KnowledgeGraph, Depends(get_knowledgegraph_object)],
42
+ knowledge_graph_query: Annotated[KnowledgeGraphQueryModel, Body()],
43
+ ) -> dict | None: # ToolResponse | None: # list[WorkspaceModel] | None:
44
+ # ) -> list[WorkspaceModel] | None:
45
+ """Query the knowledge graph for a list of workspaces matching the user query. Workspaces are entities and workspace types are entitiy types."""
46
+
47
+ if not knowledge_graph:
48
+ raise HTTPException(status_code=500, detail="Knowledge Graph is not available")
49
+
50
+ logger.info("Got context -> %s", context)
51
+ results = knowledge_graph.graph_query(
52
+ source_type=knowledge_graph_query.source_type,
53
+ source_value=knowledge_graph_query.source_value,
54
+ intermediate_types=knowledge_graph_query.intermediate_types,
55
+ target_type=knowledge_graph_query.target_type,
56
+ target_value=knowledge_graph_query.target_value,
57
+ direction=knowledge_graph_query.direction,
58
+ max_hops=4,
59
+ )
60
+ if not results:
61
+ raise HTTPException(status_code=404, detail="No result found")
62
+
63
+ where_clause = [{"workspaceID": str(workspace[1])} for workspace in results]
64
+ context_update = Context(where=where_clause, query=context.query)
65
+ logger.info("Return context -> %s", context_update)
66
+
67
+ results = [WorkspaceModel(name=n, id=i, type=knowledge_graph_query.target_type) for n, i in results]
68
+
69
+ return {"where": where_clause}
70
+
71
+ # return results
72
+
73
+
74
+ # return ToolResponse(results=results, context_update=context_update)
@@ -0,0 +1,20 @@
1
+ """Define Models for users."""
2
+
3
+ from typing import Annotated
4
+
5
+ from pydantic import BaseModel, Field
6
+
7
+
8
+ class UserModel(BaseModel):
9
+ """Defines Model for describing users in OTCS.
10
+
11
+ To display the user data as a markdown table, use the `UserModel` class.
12
+ """
13
+
14
+ user_id: Annotated[int, Field(description="ID of the user")] = None
15
+ login: Annotated[str, Field(description="Login name of the user")] = None
16
+ first_name: Annotated[str, Field(description="First name of the user")] = None
17
+ last_name: Annotated[str, Field(description="Last name of the user")] = None
18
+ email: Annotated[str, Field(description="Email address of the user")] = None
19
+ department: Annotated[str, Field(description="Department of the user")] = None
20
+ business_phone: Annotated[str, Field(description="Business phone number of the user")] = None