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
@@ -28,9 +28,10 @@ class CustomizerAPISettings(BaseSettings):
28
28
  )
29
29
  bind_address: str = Field(default="0.0.0.0", description="Interface to bind the Customizer API.") # noqa: S104
30
30
  bind_port: int = Field(default=8000, description="Port to bind the Customizer API to")
31
- workers: int = Field(default=1, description="Number of workers to use for the API BackgroundTasks")
32
- root_path: str = Field(default="/", description="Root path for the Customizer API")
31
+ workers: int = Field(default=1, description="Number of workers to use for the API background tasks")
32
+ root_path: str = Field(default="", description="Root path for the Customizer API")
33
33
  openapi_url: str = Field(default="/api/openapi.json", description="OpenAPI URL")
34
+ reload: bool = Field(default=False, description="Enable or disable the autoreload feature")
34
35
 
35
36
  concurrent_payloads: int = Field(
36
37
  default=3, description="Maximum number of concurrent payloads that are executed at the same time."
@@ -38,15 +39,15 @@ class CustomizerAPISettings(BaseSettings):
38
39
  import_payload: bool = Field(default=False)
39
40
  payload: str = Field(
40
41
  default="/payload/payload.yml.gz.b64",
41
- description="Path to a single Payload file to be loaded.",
42
+ description="Path to a single payload file to be loaded.",
42
43
  )
43
44
  payload_dir: str = Field(
44
45
  default="/payload-external/",
45
- description="Path to a directory of Payload files. All files in this directory will be loaded in alphabetical order and dependencies will be added automatically on the previous object. So all payload in this folder will be processed sequentially in alphabetical oder.",
46
+ description="Path to a directory of payload files. All files in this directory will be loaded in alphabetical order and dependencies will be added automatically on the previous object. So all payload in this folder will be processed sequentially in alphabetical oder.",
46
47
  )
47
48
  payload_dir_optional: str = Field(
48
49
  default="/payload-optional/",
49
- description="Path of Payload files to be loaded. No additional logic for dependencies will be applied, they need to be managed within the payloadSetitings section of each payload. See -> payloadOptions in the Payload Syntax documentation.",
50
+ description="Path of payload files to be loaded. No additional logic for dependencies will be applied, they need to be managed within the payloadSettings section of each payload. See -> payloadOptions in the Payload Syntax documentation.",
50
51
  )
51
52
 
52
53
  temp_dir: str = Field(
@@ -55,6 +56,9 @@ class CustomizerAPISettings(BaseSettings):
55
56
  )
56
57
 
57
58
  loglevel: Literal["INFO", "DEBUG", "WARNING", "ERROR"] = "INFO"
59
+ log_payload_processing: bool = Field(
60
+ default=False, description="Print the customizer payload processing log messages to stdout"
61
+ )
58
62
  logfolder: str = Field(
59
63
  default=os.path.join(tempfile.gettempdir(), "customizer"),
60
64
  description="Logfolder for Customizer logfiles",
@@ -68,6 +72,12 @@ class CustomizerAPISettings(BaseSettings):
68
72
  default="default",
69
73
  description="Namespace to use for otxecm resource lookups",
70
74
  )
75
+
76
+ maintenance_page: bool = Field(
77
+ default=True,
78
+ description="Start the Maintenance Page server.",
79
+ )
80
+
71
81
  maintenance_mode: bool = Field(
72
82
  default=False,
73
83
  description="Automatically enable and disable the maintenance mode during payload deployments.",
@@ -103,7 +113,7 @@ class CustomizerAPISettings(BaseSettings):
103
113
  )
104
114
 
105
115
  csai: bool = Field(
106
- default=True,
116
+ default=False,
107
117
  description="Enable the CSAI integration",
108
118
  )
109
119
 
@@ -112,6 +122,11 @@ class CustomizerAPISettings(BaseSettings):
112
122
  description="Prefix for the CSAI",
113
123
  )
114
124
 
125
+ csai_studio_integration: bool = Field(
126
+ default=False,
127
+ description="Enable the CSAI Studio Integration",
128
+ )
129
+
115
130
  upload_folder: str = Field(default=os.path.join(tempfile.gettempdir(), "upload"), description="Folder for uploads")
116
131
 
117
132
  upload_key: str = Field(default=str(uuid.uuid4()), description="Upload key for the Logs")
@@ -10,7 +10,7 @@ import subprocess
10
10
 
11
11
  from fastapi import APIRouter, HTTPException, Query, WebSocket, WebSocketDisconnect, status
12
12
 
13
- from pyxecm.customizer.api.auth.functions import get_authorized_user, get_current_user
13
+ from pyxecm_api.auth.functions import get_authorized_user, get_current_user
14
14
 
15
15
  router = APIRouter(tags=["terminal"])
16
16
 
@@ -4,20 +4,22 @@ import logging
4
4
  from http import HTTPStatus
5
5
  from typing import Annotated
6
6
 
7
- from fastapi import APIRouter, Body, Depends
8
- from fastapi.responses import JSONResponse
9
-
10
- from pyxecm.customizer.api.auth.functions import get_authorized_user
11
- from pyxecm.customizer.api.auth.models import User
12
- from pyxecm.customizer.api.common.functions import get_k8s_object, get_otcs_object, get_settings
13
- from pyxecm.customizer.api.settings import CustomizerAPISettings
14
- from pyxecm.customizer.api.v1_csai.models import CSAIEmbedMetadata
15
- from pyxecm.customizer.k8s import K8s
7
+ from fastapi import APIRouter, Body, Depends, Query
8
+ from fastapi.responses import HTMLResponse, JSONResponse
16
9
  from pyxecm.otcs import OTCS
10
+ from pyxecm_customizer.k8s import K8s
11
+
12
+ from pyxecm_api.agents.functions import get_otca_object
13
+ from pyxecm_api.auth.functions import get_authorized_user
14
+ from pyxecm_api.auth.models import User
15
+ from pyxecm_api.common.functions import get_k8s_object, get_otcs_object, get_settings
16
+ from pyxecm_api.settings import CustomizerAPISettings
17
+
18
+ from .models import CSAIEmbedMetadata
17
19
 
18
20
  router = APIRouter(prefix="/api/v1/csai", tags=["csai"])
19
21
 
20
- logger = logging.getLogger("pyxecm.customizer.api.v1_csai")
22
+ logger = logging.getLogger("pyxecm_api.v1_csai")
21
23
 
22
24
 
23
25
  @router.post("/metadata")
@@ -110,3 +112,30 @@ def set_csai_config_data(
110
112
  k8s_object.restart_deployment(deployment)
111
113
 
112
114
  return get_csai_config_data(user=user, k8s_object=k8s_object, settings=settings)
115
+
116
+
117
+ @router.get("/graph")
118
+ def get_csai_graph(name: Annotated[str, Query(..., description="Name of the Graph")]) -> HTMLResponse:
119
+ """Display the graph of the given name.
120
+
121
+ Args:
122
+ otca (Annotated[OTCA, Depends): Generic OTCA Objec
123
+ name (str): name of the graph
124
+
125
+ Returns:
126
+ HTMLResponse: _description_
127
+
128
+ """
129
+ otca = get_otca_object(otcs_object=None)
130
+
131
+ graphs = otca.get_graphs()
132
+ graph = [g for g in graphs if g["name"] == name]
133
+
134
+ if graph:
135
+ filename = otca.visualize_graph(graph[0]["id"])
136
+
137
+ with open(filename) as f:
138
+ file_content = f.read()
139
+
140
+ logger.info("name: %s", name)
141
+ return HTMLResponse(status_code=200, content=file_content)
@@ -0,0 +1,189 @@
1
+ function neighbourhoodHighlight(params) {
2
+ // console.log("in nieghbourhoodhighlight");
3
+ allNodes = nodes.get({ returnType: "Object" });
4
+ // originalNodes = JSON.parse(JSON.stringify(allNodes));
5
+ // if something is selected:
6
+ if (params.nodes.length > 0) {
7
+ highlightActive = true;
8
+ var i, j;
9
+ var selectedNode = params.nodes[0];
10
+ var degrees = 2;
11
+
12
+ // mark all nodes as hard to read.
13
+ for (let nodeId in allNodes) {
14
+ // nodeColors[nodeId] = allNodes[nodeId].color;
15
+ allNodes[nodeId].color = "rgba(200,200,200,0.5)";
16
+ if (allNodes[nodeId].hiddenLabel === undefined) {
17
+ allNodes[nodeId].hiddenLabel = allNodes[nodeId].label;
18
+ allNodes[nodeId].label = undefined;
19
+ }
20
+ }
21
+ var connectedNodes = network.getConnectedNodes(selectedNode);
22
+ var allConnectedNodes = [];
23
+
24
+ // get the second degree nodes
25
+ for (i = 1; i < degrees; i++) {
26
+ for (j = 0; j < connectedNodes.length; j++) {
27
+ allConnectedNodes = allConnectedNodes.concat(
28
+ network.getConnectedNodes(connectedNodes[j])
29
+ );
30
+ }
31
+ }
32
+
33
+ // all second degree nodes get a different color and their label back
34
+ for (i = 0; i < allConnectedNodes.length; i++) {
35
+ // allNodes[allConnectedNodes[i]].color = "pink";
36
+ allNodes[allConnectedNodes[i]].color = "rgba(150,150,150,0.75)";
37
+ if (allNodes[allConnectedNodes[i]].hiddenLabel !== undefined) {
38
+ allNodes[allConnectedNodes[i]].label =
39
+ allNodes[allConnectedNodes[i]].hiddenLabel;
40
+ allNodes[allConnectedNodes[i]].hiddenLabel = undefined;
41
+ }
42
+ }
43
+
44
+ // all first degree nodes get their own color and their label back
45
+ for (i = 0; i < connectedNodes.length; i++) {
46
+ // allNodes[connectedNodes[i]].color = undefined;
47
+ allNodes[connectedNodes[i]].color = nodeColors[connectedNodes[i]];
48
+ if (allNodes[connectedNodes[i]].hiddenLabel !== undefined) {
49
+ allNodes[connectedNodes[i]].label =
50
+ allNodes[connectedNodes[i]].hiddenLabel;
51
+ allNodes[connectedNodes[i]].hiddenLabel = undefined;
52
+ }
53
+ }
54
+
55
+ // the main node gets its own color and its label back.
56
+ // allNodes[selectedNode].color = undefined;
57
+ allNodes[selectedNode].color = nodeColors[selectedNode];
58
+ if (allNodes[selectedNode].hiddenLabel !== undefined) {
59
+ allNodes[selectedNode].label = allNodes[selectedNode].hiddenLabel;
60
+ allNodes[selectedNode].hiddenLabel = undefined;
61
+ }
62
+ } else if (highlightActive === true) {
63
+ // console.log("highlightActive was true");
64
+ // reset all nodes
65
+ for (let nodeId in allNodes) {
66
+ // allNodes[nodeId].color = "purple";
67
+ allNodes[nodeId].color = nodeColors[nodeId];
68
+ // delete allNodes[nodeId].color;
69
+ if (allNodes[nodeId].hiddenLabel !== undefined) {
70
+ allNodes[nodeId].label = allNodes[nodeId].hiddenLabel;
71
+ allNodes[nodeId].hiddenLabel = undefined;
72
+ }
73
+ }
74
+ highlightActive = false;
75
+ }
76
+
77
+ // transform the object into an array
78
+ var updateArray = [];
79
+ if (params.nodes.length > 0) {
80
+ for (let nodeId in allNodes) {
81
+ if (allNodes.hasOwnProperty(nodeId)) {
82
+ // console.log(allNodes[nodeId]);
83
+ updateArray.push(allNodes[nodeId]);
84
+ }
85
+ }
86
+ nodes.update(updateArray);
87
+ } else {
88
+ // console.log("Nothing was selected");
89
+ for (let nodeId in allNodes) {
90
+ if (allNodes.hasOwnProperty(nodeId)) {
91
+ // console.log(allNodes[nodeId]);
92
+ // allNodes[nodeId].color = {};
93
+ updateArray.push(allNodes[nodeId]);
94
+ }
95
+ }
96
+ nodes.update(updateArray);
97
+ }
98
+ }
99
+
100
+ function filterHighlight(params) {
101
+ allNodes = nodes.get({ returnType: "Object" });
102
+ // if something is selected:
103
+ if (params.nodes.length > 0) {
104
+ filterActive = true;
105
+ let selectedNodes = params.nodes;
106
+
107
+ // hiding all nodes and saving the label
108
+ for (let nodeId in allNodes) {
109
+ allNodes[nodeId].hidden = true;
110
+ if (allNodes[nodeId].savedLabel === undefined) {
111
+ allNodes[nodeId].savedLabel = allNodes[nodeId].label;
112
+ allNodes[nodeId].label = undefined;
113
+ }
114
+ }
115
+
116
+ for (let i=0; i < selectedNodes.length; i++) {
117
+ allNodes[selectedNodes[i]].hidden = false;
118
+ if (allNodes[selectedNodes[i]].savedLabel !== undefined) {
119
+ allNodes[selectedNodes[i]].label = allNodes[selectedNodes[i]].savedLabel;
120
+ allNodes[selectedNodes[i]].savedLabel = undefined;
121
+ }
122
+ }
123
+
124
+ } else if (filterActive === true) {
125
+ // reset all nodes
126
+ for (let nodeId in allNodes) {
127
+ allNodes[nodeId].hidden = false;
128
+ if (allNodes[nodeId].savedLabel !== undefined) {
129
+ allNodes[nodeId].label = allNodes[nodeId].savedLabel;
130
+ allNodes[nodeId].savedLabel = undefined;
131
+ }
132
+ }
133
+ filterActive = false;
134
+ }
135
+
136
+ // transform the object into an array
137
+ var updateArray = [];
138
+ if (params.nodes.length > 0) {
139
+ for (let nodeId in allNodes) {
140
+ if (allNodes.hasOwnProperty(nodeId)) {
141
+ updateArray.push(allNodes[nodeId]);
142
+ }
143
+ }
144
+ nodes.update(updateArray);
145
+ } else {
146
+ for (let nodeId in allNodes) {
147
+ if (allNodes.hasOwnProperty(nodeId)) {
148
+ updateArray.push(allNodes[nodeId]);
149
+ }
150
+ }
151
+ nodes.update(updateArray);
152
+ }
153
+ }
154
+
155
+ function selectNode(nodes) {
156
+ network.selectNodes(nodes);
157
+ neighbourhoodHighlight({ nodes: nodes });
158
+ return nodes;
159
+ }
160
+
161
+ function selectNodes(nodes) {
162
+ network.selectNodes(nodes);
163
+ filterHighlight({nodes: nodes});
164
+ return nodes;
165
+ }
166
+
167
+ function highlightFilter(filter) {
168
+ let selectedNodes = []
169
+ let selectedProp = filter['property']
170
+ if (filter['item'] === 'node') {
171
+ let allNodes = nodes.get({ returnType: "Object" });
172
+ for (let nodeId in allNodes) {
173
+ if (allNodes[nodeId][selectedProp] && filter['value'].includes((allNodes[nodeId][selectedProp]).toString())) {
174
+ selectedNodes.push(nodeId)
175
+ }
176
+ }
177
+ }
178
+ else if (filter['item'] === 'edge'){
179
+ let allEdges = edges.get({returnType: 'object'});
180
+ // check if the selected property exists for selected edge and select the nodes connected to the edge
181
+ for (let edge in allEdges) {
182
+ if (allEdges[edge][selectedProp] && filter['value'].includes((allEdges[edge][selectedProp]).toString())) {
183
+ selectedNodes.push(allEdges[edge]['from'])
184
+ selectedNodes.push(allEdges[edge]['to'])
185
+ }
186
+ }
187
+ }
188
+ selectNodes(selectedNodes)
189
+ }