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.
- pyxecm/coreshare.py +5 -3
- pyxecm/helper/data.py +4 -4
- pyxecm/helper/otel_config.py +26 -0
- pyxecm/helper/web.py +1 -2
- pyxecm/otca.py +1356 -16
- pyxecm/otcs.py +2354 -593
- pyxecm/otds.py +1 -1
- pyxecm/otmm.py +4 -5
- pyxecm/py.typed +0 -0
- pyxecm-3.0.0.dist-info/METADATA +48 -0
- pyxecm-3.0.0.dist-info/RECORD +96 -0
- {pyxecm-2.0.4.dist-info → pyxecm-3.0.0.dist-info}/WHEEL +1 -2
- pyxecm-3.0.0.dist-info/entry_points.txt +4 -0
- {pyxecm/customizer/api → pyxecm_api}/__main__.py +1 -1
- pyxecm_api/agents/__init__.py +7 -0
- pyxecm_api/agents/app.py +13 -0
- pyxecm_api/agents/functions.py +119 -0
- pyxecm_api/agents/models.py +10 -0
- pyxecm_api/agents/otcm_knowledgegraph/functions.py +85 -0
- pyxecm_api/agents/otcm_knowledgegraph/models.py +61 -0
- pyxecm_api/agents/otcm_knowledgegraph/router.py +74 -0
- pyxecm_api/agents/otcm_user_agent/models.py +20 -0
- pyxecm_api/agents/otcm_user_agent/router.py +65 -0
- pyxecm_api/agents/otcm_workspace_agent/models.py +40 -0
- pyxecm_api/agents/otcm_workspace_agent/router.py +200 -0
- pyxecm_api/app.py +221 -0
- {pyxecm/customizer/api → pyxecm_api}/auth/functions.py +10 -2
- {pyxecm/customizer/api → pyxecm_api}/auth/router.py +4 -3
- {pyxecm/customizer/api → pyxecm_api}/common/functions.py +39 -9
- {pyxecm/customizer/api → pyxecm_api}/common/metrics.py +1 -2
- {pyxecm/customizer/api → pyxecm_api}/common/router.py +7 -8
- {pyxecm/customizer/api → pyxecm_api}/settings.py +21 -6
- {pyxecm/customizer/api → pyxecm_api}/terminal/router.py +1 -1
- {pyxecm/customizer/api → pyxecm_api}/v1_csai/router.py +39 -10
- pyxecm_api/v1_csai/statics/bindings/utils.js +189 -0
- pyxecm_api/v1_csai/statics/tom-select/tom-select.complete.min.js +356 -0
- pyxecm_api/v1_csai/statics/tom-select/tom-select.css +334 -0
- pyxecm_api/v1_csai/statics/vis-9.1.2/vis-network.css +1 -0
- pyxecm_api/v1_csai/statics/vis-9.1.2/vis-network.min.js +27 -0
- pyxecm_api/v1_maintenance/__init__.py +1 -0
- {pyxecm/customizer/api → pyxecm_api}/v1_maintenance/functions.py +3 -3
- {pyxecm/customizer/api → pyxecm_api}/v1_maintenance/router.py +8 -8
- pyxecm_api/v1_otcs/__init__.py +1 -0
- {pyxecm/customizer/api → pyxecm_api}/v1_otcs/functions.py +7 -5
- {pyxecm/customizer/api → pyxecm_api}/v1_otcs/router.py +8 -7
- pyxecm_api/v1_payload/__init__.py +1 -0
- {pyxecm/customizer/api → pyxecm_api}/v1_payload/functions.py +10 -7
- {pyxecm/customizer/api → pyxecm_api}/v1_payload/router.py +11 -10
- {pyxecm/customizer → pyxecm_customizer}/__init__.py +8 -0
- {pyxecm/customizer → pyxecm_customizer}/__main__.py +15 -21
- {pyxecm/customizer → pyxecm_customizer}/browser_automation.py +414 -103
- {pyxecm/customizer → pyxecm_customizer}/customizer.py +178 -116
- {pyxecm/customizer → pyxecm_customizer}/guidewire.py +60 -20
- {pyxecm/customizer → pyxecm_customizer}/k8s.py +4 -4
- pyxecm_customizer/knowledge_graph.py +719 -0
- pyxecm_customizer/log.py +35 -0
- {pyxecm/customizer → pyxecm_customizer}/m365.py +41 -33
- {pyxecm/customizer → pyxecm_customizer}/payload.py +2265 -1933
- {pyxecm/customizer/api/common → pyxecm_customizer}/payload_list.py +18 -55
- {pyxecm/customizer → pyxecm_customizer}/salesforce.py +1 -1
- {pyxecm/customizer → pyxecm_customizer}/sap.py +6 -2
- {pyxecm/customizer → pyxecm_customizer}/servicenow.py +2 -4
- {pyxecm/customizer → pyxecm_customizer}/settings.py +7 -6
- {pyxecm/customizer → pyxecm_customizer}/successfactors.py +40 -28
- {pyxecm/customizer → pyxecm_customizer}/translate.py +1 -1
- {pyxecm/maintenance_page → pyxecm_maintenance_page}/__main__.py +1 -1
- {pyxecm/maintenance_page → pyxecm_maintenance_page}/app.py +14 -8
- pyxecm/customizer/api/app.py +0 -157
- pyxecm/customizer/log.py +0 -107
- pyxecm/customizer/nhc.py +0 -1169
- pyxecm/customizer/openapi.py +0 -258
- pyxecm/customizer/pht.py +0 -1357
- pyxecm-2.0.4.dist-info/METADATA +0 -119
- pyxecm-2.0.4.dist-info/RECORD +0 -78
- pyxecm-2.0.4.dist-info/licenses/LICENSE +0 -202
- pyxecm-2.0.4.dist-info/top_level.txt +0 -1
- {pyxecm/customizer/api → pyxecm_api}/__init__.py +0 -0
- {pyxecm/customizer/api/auth → pyxecm_api/agents/otcm_knowledgegraph}/__init__.py +0 -0
- {pyxecm/customizer/api/common → pyxecm_api/agents/otcm_user_agent}/__init__.py +0 -0
- {pyxecm/customizer/api/v1_csai → pyxecm_api/agents/otcm_workspace_agent}/__init__.py +0 -0
- {pyxecm/customizer/api/v1_maintenance → pyxecm_api/auth}/__init__.py +0 -0
- {pyxecm/customizer/api → pyxecm_api}/auth/models.py +0 -0
- {pyxecm/customizer/api/v1_otcs → pyxecm_api/common}/__init__.py +0 -0
- {pyxecm/customizer/api → pyxecm_api}/common/models.py +0 -0
- {pyxecm/customizer/api → pyxecm_api}/terminal/__init__.py +0 -0
- {pyxecm/customizer/api/v1_payload → pyxecm_api/v1_csai}/__init__.py +0 -0
- {pyxecm/customizer/api → pyxecm_api}/v1_csai/models.py +0 -0
- {pyxecm/customizer/api → pyxecm_api}/v1_maintenance/models.py +0 -0
- {pyxecm/customizer/api → pyxecm_api}/v1_payload/models.py +0 -0
- {pyxecm/customizer → pyxecm_customizer}/exceptions.py +0 -0
- {pyxecm/maintenance_page → pyxecm_maintenance_page}/__init__.py +0 -0
- {pyxecm/maintenance_page → pyxecm_maintenance_page}/settings.py +0 -0
- {pyxecm/maintenance_page → pyxecm_maintenance_page}/static/favicon.avif +0 -0
- {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
|
|
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=
|
|
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=
|
|
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
|
-
|
|
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,,
|
|
@@ -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"]
|
pyxecm_api/agents/app.py
ADDED
|
@@ -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,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
|